diff --git a/.idea/runConfigurations/All_Tests.xml b/.idea/runConfigurations/All_Tests.xml index 377a192e945..bf876130bd6 100644 --- a/.idea/runConfigurations/All_Tests.xml +++ b/.idea/runConfigurations/All_Tests.xml @@ -22,6 +22,7 @@ + diff --git a/annotations/com/intellij/codeInsight/annotations.xml b/annotations/com/intellij/codeInsight/annotations.xml new file mode 100644 index 00000000000..0ef0480992d --- /dev/null +++ b/annotations/com/intellij/codeInsight/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/annotations/com/intellij/lang/annotations.xml b/annotations/com/intellij/lang/annotations.xml index f603cab30a6..ebed995bb20 100644 --- a/annotations/com/intellij/lang/annotations.xml +++ b/annotations/com/intellij/lang/annotations.xml @@ -2,4 +2,8 @@ + + + \ No newline at end of file diff --git a/build.xml b/build.xml index 1862125cb6e..5ae5de6105d 100644 --- a/build.xml +++ b/build.xml @@ -474,6 +474,16 @@ void stop(); void dispose(); } + + -keepclassmembers class org.jetbrains.org.objectweb.asm.Opcodes { + *** ASM5; + } + + -keepclassmembers class org.jetbrains.org.objectweb.asm.ClassReader { + *** SKIP_CODE; + *** SKIP_DEBUG; + *** SKIP_FRAMES; + } ]]> diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java index cb573329da2..df2af34a135 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java @@ -85,7 +85,10 @@ public abstract class AnnotationCodegen { bindingContext = typeMapper.getBindingContext(); } - public void genAnnotations(Annotated annotated) { + /** + * @param returnType can be null if not applicable (e.g. {@code annotated} is a class) + */ + public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType) { if (annotated == null) { return; } @@ -111,7 +114,7 @@ public abstract class AnnotationCodegen { } if (modifierList == null) { - generateAdditionalAnnotations(annotated, Collections.emptySet()); + generateAdditionalAnnotations(annotated, returnType, Collections.emptySet()); return; } @@ -131,10 +134,14 @@ public abstract class AnnotationCodegen { } } - generateAdditionalAnnotations(annotated, annotationDescriptorsAlreadyPresent); + generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent); } - private void generateAdditionalAnnotations(@NotNull Annotated annotated, @NotNull Set annotationDescriptorsAlreadyPresent) { + private void generateAdditionalAnnotations( + @NotNull Annotated annotated, + @Nullable Type returnType, + @NotNull Set annotationDescriptorsAlreadyPresent + ) { if (annotated instanceof CallableDescriptor) { CallableDescriptor descriptor = (CallableDescriptor) annotated; @@ -142,7 +149,9 @@ public abstract class AnnotationCodegen { if (isInvisibleFromTheOutside(descriptor)) return; if (descriptor instanceof ValueParameterDescriptor && isInvisibleFromTheOutside(descriptor.getContainingDeclaration())) return; - generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent); + if (returnType != null && !AsmUtil.isPrimitive(returnType)) { + generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent); + } } } @@ -166,7 +175,6 @@ public abstract class AnnotationCodegen { } boolean isNullableType = JvmCodegenUtil.isNullableType(type); - if (!isNullableType && KotlinBuiltIns.getInstance().isPrimitiveType(type)) return; Class annotationClass = isNullableType ? Nullable.class : NotNull.class; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index b92daaf9f44..60cbe9f7dcc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -722,7 +722,7 @@ public class ExpressionCodegen extends JetVisitor implem invokeFunction(fakeCall, StackValue.local(iteratorVarIndex, asmTypeForIterator), hasNextCall); JetType type = hasNextCall.getResultingDescriptor().getReturnType(); - assert type != null && JetTypeChecker.INSTANCE.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType()); + assert type != null && JetTypeChecker.DEFAULT.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType()); Type asmType = asmType(type); StackValue.coerce(asmType, Type.BOOLEAN_TYPE, v); @@ -3413,6 +3413,11 @@ The "returned" value of try expression with no finally is either the last expres myFrameMap.leave(descriptor); + Label clauseEnd = new Label(); + v.mark(clauseEnd); + + v.visitLocalVariable(descriptor.getName().asString(), descriptorType.getDescriptor(), null, clauseStart, clauseEnd, index); + genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null); generateExceptionTable(clauseStart, tryBlockRegions, descriptorType.getInternalName()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index c2dbc72820a..6d859f6d627 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -143,7 +143,7 @@ public class FunctionCodegen extends ParentCodegenAware { v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod); } - AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor); + AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, asmMethod.getReturnType()); generateParameterAnnotations(functionDescriptor, mv, jvmSignature); @@ -180,7 +180,8 @@ public class FunctionCodegen extends ParentCodegenAware { List kotlinParameterTypes = jvmSignature.getValueParameters(); for (int i = 0; i < kotlinParameterTypes.size(); i++) { - JvmMethodParameterKind kind = kotlinParameterTypes.get(i).getKind(); + JvmMethodParameterSignature parameterSignature = kotlinParameterTypes.get(i); + JvmMethodParameterKind kind = parameterSignature.getKind(); if (kind.isSkippedInGenericSignature()) { markEnumOrInnerConstructorParameterAsSynthetic(mv, i); continue; @@ -189,7 +190,7 @@ public class FunctionCodegen extends ParentCodegenAware { if (kind == JvmMethodParameterKind.VALUE) { ValueParameterDescriptor parameter = iterator.next(); v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i); - AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter); + AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter, parameterSignature.getAsmType()); } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index df1b6cc5342..15ef11f2960 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -54,7 +54,6 @@ import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmClassSignature; import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterKind; import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignature; import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature; -import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; @@ -67,10 +66,7 @@ import org.jetbrains.org.objectweb.asm.commons.Method; import java.util.*; import static org.jetbrains.jet.codegen.AsmUtil.*; -import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.DelegationToTraitImpl; -import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin; import static org.jetbrains.jet.codegen.JvmCodegenUtil.*; -import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; @@ -78,6 +74,9 @@ import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass; +import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.DelegationToTraitImpl; +import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin; +import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN; import static org.jetbrains.org.objectweb.asm.Opcodes.*; public class ImplementationBodyCodegen extends ClassBodyCodegen { @@ -208,7 +207,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { writeInnerClasses(); - AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor); + AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor, null); } @Override @@ -485,7 +484,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { JetType returnType = function.getReturnType(); assert returnType != null : function.toString(); JetType paramType = function.getValueParameters().get(0).getType(); - if (JetTypeChecker.INSTANCE.equalTypes(arrayType, returnType) && JetTypeChecker.INSTANCE.equalTypes(arrayType, paramType)) { + if (JetTypeChecker.DEFAULT.equalTypes(arrayType, returnType) && JetTypeChecker.DEFAULT.equalTypes(arrayType, paramType)) { return true; } } @@ -1083,11 +1082,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { for (PropertyAndDefaultValue info : classObjectPropertiesToCopy) { PropertyDescriptor property = info.descriptor; + Type type = typeMapper.mapType(property); FieldVisitor fv = v.newField(OtherOrigin(property), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, context.getFieldName(property, false), - typeMapper.mapType(property).getDescriptor(), typeMapper.mapFieldSignature(property.getType()), + type.getDescriptor(), typeMapper.mapFieldSignature(property.getType()), info.defaultValue); - AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property); + AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property, type); //This field are always static and final so if it has constant initializer don't do anything in clinit, //field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4 diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index 1dc03a34674..714fe0463ab 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -145,18 +145,15 @@ public class PropertyCodegen { return false; } - FieldVisitor fv; if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) { - fv = generateBackingFieldAccess(p, descriptor); + generateBackingFieldAccess(p, descriptor); } else if (p instanceof JetProperty && ((JetProperty) p).hasDelegate()) { - fv = generatePropertyDelegateAccess((JetProperty) p, descriptor); + generatePropertyDelegateAccess((JetProperty) p, descriptor); } else { return false; } - - AnnotationCodegen.forField(fv, typeMapper).genAnnotations(descriptor); return true; } @@ -172,7 +169,7 @@ public class PropertyCodegen { if (!isTrait(context.getContextDescriptor()) || kind == OwnerKind.TRAIT_IMPL) { int flags = ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC; MethodVisitor mv = v.newMethod(OtherOrigin(descriptor), flags, name, desc, null, null); - AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(descriptor); + AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(descriptor, Type.VOID_TYPE); mv.visitCode(); mv.visitInsn(Opcodes.RETURN); mv.visitEnd(); @@ -187,7 +184,7 @@ public class PropertyCodegen { } } - private FieldVisitor generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) { + private void generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) { int modifiers = getDeprecatedAccessFlag(propertyDescriptor); for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.FIELD_FLAGS) { @@ -230,21 +227,22 @@ public class PropertyCodegen { v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, Pair.create(type, name)); - return builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(), - typeMapper.mapFieldSignature(jetType), defaultValue); + FieldVisitor fv = builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(), + typeMapper.mapFieldSignature(jetType), defaultValue); + AnnotationCodegen.forField(fv, typeMapper).genAnnotations(propertyDescriptor, type); } - private FieldVisitor generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) { + private void generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) { JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, p.getDelegateExpression()); if (delegateType == null) { // If delegate expression is unresolved reference delegateType = ErrorUtils.createErrorType("Delegate type"); } - return generateBackingField(p, propertyDescriptor, true, delegateType, null); + generateBackingField(p, propertyDescriptor, true, delegateType, null); } - private FieldVisitor generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) { + private void generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) { Object value = null; if (shouldWriteFieldInitializer(propertyDescriptor)) { @@ -254,7 +252,7 @@ public class PropertyCodegen { } } - return generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value); + generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value); } private boolean shouldWriteFieldInitializer(@NotNull PropertyDescriptor descriptor) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index 38849663539..6dee5371442 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -446,8 +446,7 @@ public class JetTypeMapper { invokeOpcode = INVOKEINTERFACE; } else { - boolean isPrivateFunInvocation = isCallInsideSameClassAsDeclared(functionDescriptor, context) && - functionDescriptor.getVisibility() == Visibilities.PRIVATE; + boolean isPrivateFunInvocation = functionDescriptor.getVisibility() == Visibilities.PRIVATE; invokeOpcode = superCall || isPrivateFunInvocation ? INVOKESPECIAL : INVOKEVIRTUAL; } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/AlternativeMethodSignatureData.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/AlternativeMethodSignatureData.java index 924c8f87f20..81f2e67463f 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/AlternativeMethodSignatureData.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/AlternativeMethodSignatureData.java @@ -139,7 +139,7 @@ public class AlternativeMethodSignatureData extends ElementAlternativeSignatureD JetType substitutedReturnType = substitutor.substitute(returnType, Variance.INVARIANT); assert substitutedReturnType != null; - if (!JetTypeChecker.INSTANCE.isSubtypeOf(altReturnType, substitutedReturnType)) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(altReturnType, substitutedReturnType)) { throw new AlternativeSignatureMismatchException( "Return type is changed to not subtype for method which overrides another: " + altReturnType + ", was: " + returnType); } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java index f8ba53037cc..b8a0da70239 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java @@ -59,8 +59,8 @@ class PropagationHeuristics { JetType elementTypeInSuper = arrayTypeFromSuper.getArguments().get(0).getType(); JetType elementType = type.getArguments().get(0).getType(); - if (JetTypeChecker.INSTANCE.isSubtypeOf(elementType, elementTypeInSuper) - && !JetTypeChecker.INSTANCE.equalTypes(elementType, elementTypeInSuper)) { + if (JetTypeChecker.DEFAULT.isSubtypeOf(elementType, elementTypeInSuper) + && !JetTypeChecker.DEFAULT.equalTypes(elementType, elementTypeInSuper)) { JetTypeImpl betterTypeInSuper = new JetTypeImpl( arrayTypeFromSuper.getAnnotations(), arrayTypeFromSuper.getConstructor(), diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassImpl.java index 39050e233d4..9bd7d799793 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassImpl.java @@ -16,10 +16,8 @@ package org.jetbrains.jet.lang.resolve.java.structure.impl; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiCompiledElement; -import com.intellij.psi.PsiTypeParameter; +import com.intellij.psi.*; +import com.intellij.psi.impl.PsiSubstitutorImpl; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -30,7 +28,9 @@ import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.jetbrains.jet.lang.resolve.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.*; @@ -181,4 +181,27 @@ public class JavaClassImpl extends JavaClassifierImpl implements JavaC return OriginKind.SOURCE; } } + + @NotNull + @Override + public JavaType createImmediateType(@NotNull JavaTypeSubstitutor substitutor) { + return new JavaClassifierTypeImpl( + JavaPsiFacade.getElementFactory(getPsi().getProject()).createType(getPsi(), createPsiSubstitutor(substitutor))); + } + + @NotNull + private static PsiSubstitutor createPsiSubstitutor(@NotNull JavaTypeSubstitutor substitutor) { + Map substMap = new HashMap(); + for (Map.Entry entry : substitutor.getSubstitutionMap().entrySet()) { + PsiTypeParameter key = ((JavaTypeParameterImpl) entry.getKey()).getPsi(); + if (entry.getValue() == null) { + substMap.put(key, null); + } + else { + substMap.put(key, ((JavaTypeImpl) entry.getValue()).getPsi()); + } + } + + return PsiSubstitutorImpl.createSubstitutor(substMap); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassifierTypeImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassifierTypeImpl.java index 13493d162c6..d91be1c9ca7 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassifierTypeImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassifierTypeImpl.java @@ -16,20 +16,12 @@ package org.jetbrains.jet.lang.resolve.java.structure.impl; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiClassType; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifier; -import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifierType; -import org.jetbrains.jet.lang.resolve.java.structure.JavaType; -import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeSubstitutor; +import org.jetbrains.jet.lang.resolve.java.structure.*; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; import static org.jetbrains.jet.lang.resolve.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.types; @@ -68,13 +60,25 @@ public class JavaClassifierTypeImpl extends JavaTypeImpl implement if (resolutionResult == null) { PsiClassType.ClassResolveResult result = getPsi().resolveGenerics(); PsiClass psiClass = result.getElement(); + PsiSubstitutor substitutor = result.getSubstitutor(); resolutionResult = new ResolutionResult( psiClass == null ? null : JavaClassifierImpl.create(psiClass), - new JavaTypeSubstitutorImpl(result.getSubstitutor()) + new JavaTypeSubstitutorImpl(convertSubstitutionMap(substitutor.getSubstitutionMap())) ); } } + @NotNull + private Map convertSubstitutionMap(@NotNull Map psiMap) { + Map substitutionMap = new HashMap(); + for (Map.Entry entry : psiMap.entrySet()) { + PsiType value = entry.getValue(); + substitutionMap.put(new JavaTypeParameterImpl(entry.getKey()), value == null ? null : JavaTypeImpl.create(value)); + } + + return substitutionMap; + } + @Override @NotNull public Collection getSupertypes() { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeImpl.java index 680d5c53cdb..d859abdba9c 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeImpl.java @@ -39,31 +39,31 @@ public abstract class JavaTypeImpl implements JavaType { return psiType.accept(new PsiTypeVisitor>() { @Nullable @Override - public JavaTypeImpl visitType(PsiType type) { + public JavaTypeImpl visitType(@NotNull PsiType type) { throw new UnsupportedOperationException("Unsupported PsiType: " + type); } @Nullable @Override - public JavaTypeImpl visitPrimitiveType(PsiPrimitiveType primitiveType) { + public JavaTypeImpl visitPrimitiveType(@NotNull PsiPrimitiveType primitiveType) { return new JavaPrimitiveTypeImpl(primitiveType); } @Nullable @Override - public JavaTypeImpl visitArrayType(PsiArrayType arrayType) { + public JavaTypeImpl visitArrayType(@NotNull PsiArrayType arrayType) { return new JavaArrayTypeImpl(arrayType); } @Nullable @Override - public JavaTypeImpl visitClassType(PsiClassType classType) { + public JavaTypeImpl visitClassType(@NotNull PsiClassType classType) { return new JavaClassifierTypeImpl(classType); } @Nullable @Override - public JavaTypeImpl visitWildcardType(PsiWildcardType wildcardType) { + public JavaTypeImpl visitWildcardType(@NotNull PsiWildcardType wildcardType) { return new JavaWildcardTypeImpl(wildcardType); } }); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeProviderImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeProviderImpl.java index 45ad66eaf8a..6c45f61f0ad 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeProviderImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeProviderImpl.java @@ -18,10 +18,12 @@ package org.jetbrains.jet.lang.resolve.java.structure.impl; import com.intellij.psi.PsiManager; import com.intellij.psi.PsiType; +import com.intellij.psi.PsiWildcardType; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.resolve.java.structure.JavaType; import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeProvider; +import org.jetbrains.jet.lang.resolve.java.structure.JavaWildcardType; public class JavaTypeProviderImpl implements JavaTypeProvider { private final PsiManager manager; @@ -35,4 +37,22 @@ public class JavaTypeProviderImpl implements JavaTypeProvider { public JavaType createJavaLangObjectType() { return JavaTypeImpl.create(PsiType.getJavaLangObject(manager, GlobalSearchScope.allScope(manager.getProject()))); } + + @NotNull + @Override + public JavaWildcardType createUpperBoundWildcard(@NotNull JavaType bound) { + return new JavaWildcardTypeImpl(PsiWildcardType.createExtends(manager, ((JavaTypeImpl) bound).getPsi())); + } + + @NotNull + @Override + public JavaWildcardType createLowerBoundWildcard(@NotNull JavaType bound) { + return new JavaWildcardTypeImpl(PsiWildcardType.createSuper(manager, ((JavaTypeImpl) bound).getPsi())); + } + + @NotNull + @Override + public JavaWildcardType createUnboundedWildcard() { + return new JavaWildcardTypeImpl(PsiWildcardType.createUnbounded(manager)); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeSubstitutorImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeSubstitutorImpl.java index 9983a52bcf3..146d79a5e86 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeSubstitutorImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeSubstitutorImpl.java @@ -16,83 +16,170 @@ package org.jetbrains.jet.lang.resolve.java.structure.impl; -import com.intellij.psi.PsiSubstitutor; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiTypeParameter; -import com.intellij.psi.impl.PsiSubstitutorImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.java.structure.JavaType; -import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeParameter; -import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeSubstitutor; +import org.jetbrains.jet.lang.resolve.java.structure.*; +import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; public class JavaTypeSubstitutorImpl implements JavaTypeSubstitutor { - private final PsiSubstitutor psiSubstitutor; - private Map substitutionMap; + private final Map substitutionMap; - public JavaTypeSubstitutorImpl(@NotNull PsiSubstitutor psiSubstitutor) { - this.psiSubstitutor = psiSubstitutor; - } - - public JavaTypeSubstitutorImpl(@NotNull PsiSubstitutor psiSubstitutor, @NotNull Map substitutionMap) { - this(psiSubstitutor); + public JavaTypeSubstitutorImpl(@NotNull Map substitutionMap) { this.substitutionMap = substitutionMap; } @NotNull - public static JavaTypeSubstitutor create(@NotNull Map substitutionMap) { - Map psiMap = new HashMap(); - for (Map.Entry entry : substitutionMap.entrySet()) { - JavaTypeImpl value = ((JavaTypeImpl) entry.getValue()); - psiMap.put(((JavaTypeParameterImpl) entry.getKey()).getPsi(), value == null ? null : value.getPsi()); - } - PsiSubstitutor psiSubstitutor = PsiSubstitutorImpl.createSubstitutor(psiMap); - return new JavaTypeSubstitutorImpl(psiSubstitutor, substitutionMap); + @Override + public JavaType substitute(@NotNull JavaType type) { + JavaType substitutedType = substituteInternal(type); + return substitutedType != null ? substitutedType : correctSubstitutionForRawType(type); } - @Override @NotNull - public JavaType substitute(@NotNull JavaType type) { - return JavaTypeImpl.create(psiSubstitutor.substitute(((JavaTypeImpl) type).getPsi())); + // In case of raw type we get substition map like T -> null, + // in this case we should substitute upper bound of T or, + // if it does not exist, return java.lang.Object + private JavaType correctSubstitutionForRawType(@NotNull JavaType original) { + if (original instanceof JavaClassifierType) { + JavaClassifier classifier = ((JavaClassifierType) original).getClassifier(); + if (classifier instanceof JavaTypeParameter) { + return rawTypeForTypeParameter((JavaTypeParameter) classifier); + } + } + + return original; + } + + @Nullable + private JavaType substituteInternal(@NotNull JavaType type) { + if (type instanceof JavaClassifierType) { + JavaClassifierType classifierType = (JavaClassifierType) type; + JavaClassifier classifier = classifierType.getClassifier(); + + if (classifier instanceof JavaTypeParameter) { + return substitute((JavaTypeParameter) classifier); + } + else if (classifier instanceof JavaClass) { + JavaClass javaClass = (JavaClass) classifier; + Map substMap = new HashMap(); + processClass(javaClass, classifierType.getSubstitutor(), substMap); + + return javaClass.createImmediateType(new JavaTypeSubstitutorImpl(substMap)); + } + + return type; + } + else if (type instanceof JavaPrimitiveType) { + return type; + } + else if (type instanceof JavaArrayType) { + JavaType componentType = ((JavaArrayType) type).getComponentType(); + JavaType substitutedComponentType = substitute(componentType); + if (substitutedComponentType == componentType) return type; + + return substitutedComponentType.createArrayType(); + } + else if (type instanceof JavaWildcardType) { + return substituteWildcardType((JavaWildcardType) type); + } + + return type; + } + + private void processClass(@NotNull JavaClass javaClass, @NotNull JavaTypeSubstitutor substitutor, @NotNull Map substMap) { + List typeParameters = javaClass.getTypeParameters(); + for (JavaTypeParameter typeParameter : typeParameters) { + JavaType substitutedParam = substitutor.substitute(typeParameter); + if (substitutedParam == null) { + substMap.put(typeParameter, null); + } + else { + substMap.put(typeParameter, substituteInternal(substitutedParam)); + } + } + + if (javaClass.isStatic()) { + return; + } + + JavaClass outerClass = javaClass.getOuterClass(); + if (outerClass != null) { + processClass(outerClass, substitutor, substMap); + } + } + + @Nullable + private JavaType substituteWildcardType(@NotNull JavaWildcardType wildcardType) { + JavaType bound = wildcardType.getBound(); + if (bound == null) { + return wildcardType; + } + + JavaType newBound = substituteInternal(bound); + if (newBound == null) { + // This can be in case of substitution wildcard to raw type + return null; + } + + return rebound(wildcardType, newBound); + } + + @NotNull + private static JavaWildcardType rebound(@NotNull JavaWildcardType type, @NotNull JavaType newBound) { + if (type.getTypeProvider().createJavaLangObjectType().equals(newBound)) { + return type.getTypeProvider().createUnboundedWildcard(); + } + + if (type.isExtends()) { + return type.getTypeProvider().createUpperBoundWildcard(newBound); + } + else { + return type.getTypeProvider().createLowerBoundWildcard(newBound); + } + } + + @NotNull + private JavaType rawTypeForTypeParameter(@NotNull JavaTypeParameter typeParameter) { + Collection bounds = typeParameter.getUpperBounds(); + if (!bounds.isEmpty()) { + return substitute(bounds.iterator().next()); + } + + return typeParameter.getTypeProvider().createJavaLangObjectType(); } @Override @Nullable public JavaType substitute(@NotNull JavaTypeParameter typeParameter) { - PsiType psiType = psiSubstitutor.substitute(((JavaTypeParameterImpl) typeParameter).getPsi()); - return psiType == null ? null : JavaTypeImpl.create(psiType); + if (substitutionMap.containsKey(typeParameter)) { + return substitutionMap.get(typeParameter); + } + + return typeParameter.getType(); } @Override @NotNull public Map getSubstitutionMap() { - if (substitutionMap == null) { - Map psiMap = psiSubstitutor.getSubstitutionMap(); - substitutionMap = new HashMap(); - for (Map.Entry entry : psiMap.entrySet()) { - PsiType value = entry.getValue(); - substitutionMap.put(new JavaTypeParameterImpl(entry.getKey()), value == null ? null : JavaTypeImpl.create(value)); - } - } - return substitutionMap; } @Override public int hashCode() { - return psiSubstitutor.hashCode(); + return substitutionMap.hashCode(); } @Override public boolean equals(Object obj) { - return obj instanceof JavaTypeSubstitutorImpl && psiSubstitutor.equals(((JavaTypeSubstitutorImpl) obj).psiSubstitutor); + return obj instanceof JavaTypeSubstitutorImpl && substitutionMap.equals(((JavaTypeSubstitutorImpl) obj).substitutionMap); } @Override public String toString() { - return getClass().getSimpleName() + ": " + psiSubstitutor; + return getClass().getSimpleName() + ": " + substitutionMap; } -} +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java index 79db9004292..957f86ec3c7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java @@ -44,8 +44,8 @@ public class CheckerTestUtil { public int compare(@NotNull Diagnostic o1, @NotNull Diagnostic o2) { List ranges1 = o1.getTextRanges(); List ranges2 = o2.getTextRanges(); - if (ranges1.size() != ranges2.size()) return ranges1.size() - ranges2.size(); - for (int i = 0; i < ranges1.size(); i++) { + int minNumberOfRanges = ranges1.size() < ranges2.size() ? ranges1.size() : ranges2.size(); + for (int i = 0; i < minNumberOfRanges; i++) { TextRange range1 = ranges1.get(i); TextRange range2 = ranges2.get(i); int startOffset1 = range1.getStartOffset(); @@ -61,7 +61,7 @@ public class CheckerTestUtil { return endOffset2 - endOffset1; } } - return 0; + return ranges1.size() - ranges2.size(); } }; private static final Pattern RANGE_START_OR_END_PATTERN = Pattern.compile("()|()"); @@ -439,41 +439,39 @@ public class CheckerTestUtil { } } - private static List getSortedDiagnosticDescriptors(Collection diagnostics) { - List list = Lists.newArrayList(diagnostics); - Collections.sort(list, DIAGNOSTIC_COMPARATOR); - - List diagnosticDescriptors = Lists.newArrayList(); - DiagnosticDescriptor currentDiagnosticDescriptor = null; - for (Diagnostic diagnostic : list) { - List textRanges = diagnostic.getTextRanges(); + @NotNull + private static List getSortedDiagnosticDescriptors(@NotNull Collection diagnostics) { + LinkedListMultimap diagnosticsGroupedByRanges = LinkedListMultimap.create(); + for (Diagnostic diagnostic : diagnostics) { if (!diagnostic.isValid()) continue; - - TextRange textRange = textRanges.get(0); - if (currentDiagnosticDescriptor != null && currentDiagnosticDescriptor.equalRange(textRange)) { - currentDiagnosticDescriptor.diagnostics.add(diagnostic); - } - else { - currentDiagnosticDescriptor = new DiagnosticDescriptor(textRange.getStartOffset(), textRange.getEndOffset(), diagnostic); - diagnosticDescriptors.add(currentDiagnosticDescriptor); + for (TextRange textRange : diagnostic.getTextRanges()) { + diagnosticsGroupedByRanges.put(textRange, diagnostic); } } + List diagnosticDescriptors = Lists.newArrayList(); + for (TextRange range : diagnosticsGroupedByRanges.keySet()) { + diagnosticDescriptors.add( + new DiagnosticDescriptor(range.getStartOffset(), range.getEndOffset(), diagnosticsGroupedByRanges.get(range))); + } + Collections.sort(diagnosticDescriptors, new Comparator() { + @Override + public int compare(DiagnosticDescriptor d1, DiagnosticDescriptor d2) { + // Start early -- go first; start at the same offset, the one who end later is the outer, i.e. goes first + return (d1.start != d2.start) ? d1.start - d2.start : d2.end - d1.end; + } + }); return diagnosticDescriptors; } private static class DiagnosticDescriptor { private final int start; private final int end; - private final List diagnostics = Lists.newArrayList(); + private final List diagnostics; - DiagnosticDescriptor(int start, int end, Diagnostic diagnostic) { + DiagnosticDescriptor(int start, int end, List diagnostics) { this.start = start; this.end = end; - this.diagnostics.add(diagnostic); - } - - public boolean equalRange(TextRange textRange) { - return start == textRange.getStartOffset() && end == textRange.getEndOffset(); + this.diagnostics = diagnostics; } public Multiset getDiagnosticTypeStrings() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 7379e15f149..5abdb9058f1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -16,7 +16,6 @@ package org.jetbrains.jet.lang.cfg; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; @@ -53,8 +52,6 @@ import org.jetbrains.jet.lexer.JetTokens; import java.util.*; import static org.jetbrains.jet.lang.cfg.JetControlFlowBuilder.PredefinedOperation.*; -import static org.jetbrains.jet.lang.cfg.JetControlFlowProcessor.CFPContext.IN_CONDITION; -import static org.jetbrains.jet.lang.cfg.JetControlFlowProcessor.CFPContext.NOT_IN_CONDITION; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lexer.JetTokens.*; @@ -83,14 +80,14 @@ public class JetControlFlowProcessor { JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine; List valueParameters = declarationWithBody.getValueParameters(); for (JetParameter valueParameter : valueParameters) { - cfpVisitor.generateInstructions(valueParameter, NOT_IN_CONDITION); + cfpVisitor.generateInstructions(valueParameter); } JetExpression bodyExpression = declarationWithBody.getBodyExpression(); if (bodyExpression != null) { - cfpVisitor.generateInstructions(bodyExpression, NOT_IN_CONDITION); + cfpVisitor.generateInstructions(bodyExpression); } } else { - cfpVisitor.generateInstructions(subroutine, NOT_IN_CONDITION); + cfpVisitor.generateInstructions(subroutine); } return builder.exitSubroutine(subroutine); } @@ -106,48 +103,33 @@ public class JetControlFlowProcessor { builder.bindLabel(afterDeclaration); } - /*package*/ enum CFPContext { - IN_CONDITION(true), - NOT_IN_CONDITION(false); - - private final boolean inCondition; - - private CFPContext(boolean inCondition) { - this.inCondition = inCondition; - } - - public boolean inCondition() { - return inCondition; - } - } - - private class CFPVisitor extends JetVisitorVoidWithParameter { + private class CFPVisitor extends JetVisitorVoid { private final JetControlFlowBuilder builder; - private final JetVisitorVoidWithParameter conditionVisitor = new JetVisitorVoidWithParameter() { + private final JetVisitorVoid conditionVisitor = new JetVisitorVoid() { @Override - public void visitWhenConditionInRangeVoid(@NotNull JetWhenConditionInRange condition, CFPContext context) { - generateInstructions(condition.getRangeExpression(), context); - generateInstructions(condition.getOperationReference(), context); + public void visitWhenConditionInRange(@NotNull JetWhenConditionInRange condition) { + generateInstructions(condition.getRangeExpression()); + generateInstructions(condition.getOperationReference()); // TODO : read the call to contains()... createNonSyntheticValue(condition, condition.getRangeExpression(), condition.getOperationReference()); } @Override - public void visitWhenConditionIsPatternVoid(@NotNull JetWhenConditionIsPattern condition, CFPContext context) { + public void visitWhenConditionIsPattern(@NotNull JetWhenConditionIsPattern condition) { // TODO: types in CF? } @Override - public void visitWhenConditionWithExpressionVoid(@NotNull JetWhenConditionWithExpression condition, CFPContext context) { - generateInstructions(condition.getExpression(), context); + public void visitWhenConditionWithExpression(@NotNull JetWhenConditionWithExpression condition) { + generateInstructions(condition.getExpression()); copyValue(condition.getExpression(), condition); } @Override - public void visitJetElementVoid(@NotNull JetElement element, CFPContext context) { + public void visitJetElement(@NotNull JetElement element) { throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString()); } }; @@ -160,9 +142,9 @@ public class JetControlFlowProcessor { builder.mark(element); } - public void generateInstructions(@Nullable JetElement element, CFPContext context) { + public void generateInstructions(@Nullable JetElement element) { if (element == null) return; - element.accept(this, context); + element.accept(this); checkNothingType(element); } @@ -266,26 +248,26 @@ public class JetControlFlowProcessor { } @Override - public void visitParenthesizedExpressionVoid(@NotNull JetParenthesizedExpression expression, CFPContext context) { + public void visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression) { mark(expression); JetExpression innerExpression = expression.getExpression(); if (innerExpression != null) { - generateInstructions(innerExpression, context); + generateInstructions(innerExpression); copyValue(innerExpression, expression); } } @Override - public void visitAnnotatedExpressionVoid(@NotNull JetAnnotatedExpression expression, CFPContext context) { + public void visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression) { JetExpression baseExpression = expression.getBaseExpression(); if (baseExpression != null) { - generateInstructions(baseExpression, context); + generateInstructions(baseExpression); copyValue(baseExpression, expression); } } @Override - public void visitThisExpressionVoid(@NotNull JetThisExpression expression, CFPContext context) { + public void visitThisExpression(@NotNull JetThisExpression expression) { ResolvedCall resolvedCall = getResolvedCall(expression); if (resolvedCall == null) { createNonSyntheticValue(expression); @@ -294,74 +276,50 @@ public class JetControlFlowProcessor { CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor(); if (resultingDescriptor instanceof ReceiverParameterDescriptor) { - builder.readVariable(expression, expression, resolvedCall, getReceiverValues(expression, resolvedCall, true)); + builder.readVariable(expression, expression, resolvedCall, getReceiverValues(resolvedCall, true)); } copyValue(expression, expression.getInstanceReference()); } @Override - public void visitConstantExpressionVoid(@NotNull JetConstantExpression expression, CFPContext context) { + public void visitConstantExpression(@NotNull JetConstantExpression expression) { CompileTimeConstant constant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression); builder.loadConstant(expression, constant); } @Override - public void visitSimpleNameExpressionVoid(@NotNull JetSimpleNameExpression expression, CFPContext context) { + public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression) { ResolvedCall resolvedCall = getResolvedCall(expression); if (resolvedCall instanceof VariableAsFunctionResolvedCall) { VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall; - generateCall(expression, expression, variableAsFunctionResolvedCall.getVariableCall()); + generateCall(expression, variableAsFunctionResolvedCall.getVariableCall()); } - else if (!generateCall(expression, expression) && !(expression.getParent() instanceof JetCallExpression)) { + else if (!generateCall(expression, true) && !(expression.getParent() instanceof JetCallExpression)) { createNonSyntheticValue(expression, generateAndGetReceiverIfAny(expression)); } } @Override - public void visitLabeledExpressionVoid(@NotNull JetLabeledExpression expression, CFPContext context) { + public void visitLabeledExpression(@NotNull JetLabeledExpression expression) { mark(expression); JetExpression baseExpression = expression.getBaseExpression(); if (baseExpression != null) { - generateInstructions(baseExpression, context); + generateInstructions(baseExpression); copyValue(baseExpression, expression); } } @SuppressWarnings("SuspiciousMethodCalls") @Override - public void visitBinaryExpressionVoid(@NotNull JetBinaryExpression expression, CFPContext context) { + public void visitBinaryExpression(@NotNull JetBinaryExpression expression) { JetSimpleNameExpression operationReference = expression.getOperationReference(); IElementType operationType = operationReference.getReferencedNameElementType(); - if (!ImmutableSet.of(ANDAND, OROR, EQ, ELVIS).contains(operationType)) { - mark(expression); - } JetExpression left = expression.getLeft(); JetExpression right = expression.getRight(); - if (operationType == ANDAND) { - generateInstructions(left, IN_CONDITION); - Label resultLabel = builder.createUnboundLabel(); - builder.jumpOnFalse(resultLabel, expression, builder.getBoundValue(left)); - if (right != null) { - generateInstructions(right, IN_CONDITION); - } - builder.bindLabel(resultLabel); - if (!context.inCondition()) { - predefinedOperation(expression, AND); - } - } - else if (operationType == OROR) { - generateInstructions(left, IN_CONDITION); - Label resultLabel = builder.createUnboundLabel(); - builder.jumpOnTrue(resultLabel, expression, builder.getBoundValue(left)); - if (right != null) { - generateInstructions(right, IN_CONDITION); - } - builder.bindLabel(resultLabel); - if (!context.inCondition()) { - predefinedOperation(expression, OR); - } + if (operationType == ANDAND || operationType == OROR) { + generateBooleanOperation(expression); } else if (operationType == EQ) { visitAssignment(left, getDeferredValue(right), expression); @@ -369,42 +327,59 @@ public class JetControlFlowProcessor { else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) { ResolvedCall resolvedCall = getResolvedCall(operationReference); if (resolvedCall != null) { - CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); + PseudoValue rhsValue = generateCall(operationReference, resolvedCall).getOutputValue(); Name assignMethodName = OperatorConventions.getNameForOperationSymbol((JetToken) expression.getOperationToken()); - if (descriptor.getName().equals(assignMethodName)) { - generateCall(expression, operationReference, resolvedCall); - } - else { + if (!resolvedCall.getResultingDescriptor().getName().equals(assignMethodName)) { /* At this point assignment of the form a += b actually means a = a + b * So we first generate call of "+" operation and then use its output pseudo-value * as a right-hand side when generating assignment call */ - Function0 rhsDeferredValue = - getValueAsFunction(generateCall(null, operationReference, resolvedCall).getOutputValue()); - visitAssignment(left, rhsDeferredValue, expression); + visitAssignment(left, getValueAsFunction(rhsValue), expression); } } else { - generateBothArguments(expression); + generateBothArgumentsAndMark(expression); } } else if (operationType == ELVIS) { - generateInstructions(left, NOT_IN_CONDITION); + generateInstructions(left); + mark(expression); Label afterElvis = builder.createUnboundLabel(); builder.jumpOnTrue(afterElvis, expression, builder.getBoundValue(left)); if (right != null) { - generateInstructions(right, NOT_IN_CONDITION); + generateInstructions(right); } builder.bindLabel(afterElvis); mergeValues(Arrays.asList(left, right), expression); } else { - if (!generateCall(expression, operationReference)) { - generateBothArguments(expression); + if (!generateCall(operationReference, true)) { + generateBothArgumentsAndMark(expression); } } } + private void generateBooleanOperation(JetBinaryExpression expression) { + IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); + JetExpression left = expression.getLeft(); + JetExpression right = expression.getRight(); + + Label resultLabel = builder.createUnboundLabel(); + generateInstructions(left); + if (operationType == ANDAND) { + builder.jumpOnFalse(resultLabel, expression, builder.getBoundValue(left)); + } + else { + builder.jumpOnTrue(resultLabel, expression, builder.getBoundValue(left)); + } + if (right != null) { + generateInstructions(right); + } + builder.bindLabel(resultLabel); + JetControlFlowBuilder.PredefinedOperation operation = operationType == ANDAND ? AND : OR; + builder.predefinedOperation(expression, operation, elementsToValues(Arrays.asList(left, right))); + } + private Function0 getValueAsFunction(final PseudoValue value) { return new Function0() { @Override @@ -418,29 +393,23 @@ public class JetControlFlowProcessor { return new Function0() { @Override public PseudoValue invoke() { - generateInstructions(expression, NOT_IN_CONDITION); + generateInstructions(expression); return builder.getBoundValue(expression); } }; } - private void predefinedOperation(JetBinaryExpression expression, JetControlFlowBuilder.PredefinedOperation operation) { - builder.predefinedOperation( - expression, operation, elementsToValues(Arrays.asList(expression.getLeft(), expression.getRight())) - ); - } - - private void generateBothArguments(JetBinaryExpression expression) { + private void generateBothArgumentsAndMark(JetBinaryExpression expression) { JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft()); if (left != null) { - generateInstructions(left, NOT_IN_CONDITION); + generateInstructions(left); } JetExpression right = expression.getRight(); if (right != null) { - generateInstructions(right, NOT_IN_CONDITION); + generateInstructions(right); } - createNonSyntheticValue(expression, left, right); + mark(expression); } private void visitAssignment(JetExpression lhs, @NotNull Function0 rhsDeferredValue, JetExpression parentExpression) { @@ -461,7 +430,7 @@ public class JetControlFlowProcessor { if (left instanceof JetSimpleNameExpression || left instanceof JetQualifiedExpression) { accessTarget = getResolvedCallAccessTarget(PsiUtilPackage.getQualifiedElementSelector(left)); if (accessTarget instanceof AccessTarget.Call) { - receiverValues = getReceiverValues(lhs, ((AccessTarget.Call) accessTarget).getResolvedCall(), true); + receiverValues = getReceiverValues(((AccessTarget.Call) accessTarget).getResolvedCall(), true); } } else if (left instanceof JetProperty) { @@ -497,9 +466,9 @@ public class JetControlFlowProcessor { mark(lhs); } - generateInstructions(lhs.getArrayExpression(), NOT_IN_CONDITION); + generateInstructions(lhs.getArrayExpression()); - Map receiverValues = getReceiverValues(lhs, setResolvedCall, false); + Map receiverValues = getReceiverValues(setResolvedCall, false); SmartFMap argumentValues = getArraySetterArguments(rhsDeferredValue, setResolvedCall); @@ -566,7 +535,7 @@ public class JetControlFlowProcessor { private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression, @Nullable ResolvedCall resolvedCall) { mark(arrayAccessExpression); - if (!checkAndGenerateCall(arrayAccessExpression, arrayAccessExpression, resolvedCall)) { + if (!checkAndGenerateCall(arrayAccessExpression, resolvedCall, true)) { generateArrayAccessWithoutCall(arrayAccessExpression); } } @@ -580,10 +549,10 @@ public class JetControlFlowProcessor { JetExpression arrayExpression = arrayAccessExpression.getArrayExpression(); inputExpressions.add(arrayExpression); - generateInstructions(arrayExpression, NOT_IN_CONDITION); + generateInstructions(arrayExpression); for (JetExpression index : arrayAccessExpression.getIndexExpressions()) { - generateInstructions(index, NOT_IN_CONDITION); + generateInstructions(index); inputExpressions.add(index); } @@ -591,14 +560,13 @@ public class JetControlFlowProcessor { } @Override - public void visitUnaryExpressionVoid(@NotNull JetUnaryExpression expression, CFPContext context) { - mark(expression); + public void visitUnaryExpression(@NotNull JetUnaryExpression expression) { JetSimpleNameExpression operationSign = expression.getOperationReference(); IElementType operationType = operationSign.getReferencedNameElementType(); JetExpression baseExpression = expression.getBaseExpression(); if (baseExpression == null) return; if (JetTokens.EXCLEXCL == operationType) { - generateInstructions(baseExpression, NOT_IN_CONDITION); + generateInstructions(baseExpression); builder.predefinedOperation(expression, NOT_NULL_ASSERTION, elementsToValues(Collections.singletonList(baseExpression))); return; } @@ -608,15 +576,18 @@ public class JetControlFlowProcessor { PseudoValue rhsValue; if (resolvedCall != null) { - rhsValue = generateCall(incrementOrDecrement ? null : expression, operationSign, resolvedCall).getOutputValue(); + rhsValue = generateCall(operationSign, resolvedCall).getOutputValue(); } else { - generateInstructions(baseExpression, NOT_IN_CONDITION); + generateInstructions(baseExpression); rhsValue = createNonSyntheticValue(expression, baseExpression); } if (incrementOrDecrement) { visitAssignment(baseExpression, getValueAsFunction(rhsValue), expression); + if (expression instanceof JetPostfixExpression) { + copyValue(baseExpression, expression); + } } } @@ -625,19 +596,19 @@ public class JetControlFlowProcessor { } @Override - public void visitIfExpressionVoid(@NotNull JetIfExpression expression, CFPContext context) { + public void visitIfExpression(@NotNull JetIfExpression expression) { mark(expression); List branches = new ArrayList(2); JetExpression condition = expression.getCondition(); if (condition != null) { - generateInstructions(condition, IN_CONDITION); + generateInstructions(condition); } Label elseLabel = builder.createUnboundLabel(); builder.jumpOnFalse(elseLabel, expression, builder.getBoundValue(condition)); JetExpression thenBranch = expression.getThen(); if (thenBranch != null) { branches.add(thenBranch); - generateInstructions(thenBranch, context); + generateInstructions(thenBranch); } else { builder.loadUnit(expression); @@ -648,7 +619,7 @@ public class JetControlFlowProcessor { JetExpression elseBranch = expression.getElse(); if (elseBranch != null) { branches.add(elseBranch); - generateInstructions(elseBranch, context); + generateInstructions(elseBranch); } else { builder.loadUnit(expression); @@ -659,13 +630,11 @@ public class JetControlFlowProcessor { private class FinallyBlockGenerator { private final JetFinallySection finallyBlock; - private final CFPContext context; private Label startFinally = null; private Label finishFinally = null; - private FinallyBlockGenerator(JetFinallySection block, CFPContext context) { + private FinallyBlockGenerator(JetFinallySection block) { finallyBlock = block; - this.context = context; } public void generate() { @@ -678,18 +647,18 @@ public class JetControlFlowProcessor { } startFinally = builder.createUnboundLabel("start finally"); builder.bindLabel(startFinally); - generateInstructions(finalExpression, context); + generateInstructions(finalExpression); finishFinally = builder.createUnboundLabel("finish finally"); builder.bindLabel(finishFinally); } } @Override - public void visitTryExpressionVoid(@NotNull JetTryExpression expression, CFPContext context) { + public void visitTryExpression(@NotNull JetTryExpression expression) { mark(expression); JetFinallySection finallyBlock = expression.getFinallyBlock(); - final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock, context); + final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock); boolean hasFinally = finallyBlock != null; if (hasFinally) { builder.enterTryFinally(new GenerationTrigger() { @@ -706,7 +675,7 @@ public class JetControlFlowProcessor { }); } - Label onExceptionToFinallyBlock = generateTryAndCatches(expression, context); + Label onExceptionToFinallyBlock = generateTryAndCatches(expression); if (hasFinally) { assert onExceptionToFinallyBlock != null : "No finally lable generated: " + expression.getText(); @@ -733,7 +702,7 @@ public class JetControlFlowProcessor { // Returns label for 'finally' block @Nullable - private Label generateTryAndCatches(@NotNull JetTryExpression expression, CFPContext context) { + private Label generateTryAndCatches(@NotNull JetTryExpression expression) { List catchClauses = expression.getCatchClauses(); boolean hasCatches = !catchClauses.isEmpty(); @@ -750,7 +719,7 @@ public class JetControlFlowProcessor { } JetBlockExpression tryBlock = expression.getTryBlock(); - generateInstructions(tryBlock, context); + generateInstructions(tryBlock); if (hasCatches) { Label afterCatches = builder.createUnboundLabel("afterCatches"); @@ -781,7 +750,7 @@ public class JetControlFlowProcessor { } JetExpression catchBody = catchClause.getCatchBody(); if (catchBody != null) { - generateInstructions(catchBody, NOT_IN_CONDITION); + generateInstructions(catchBody); } builder.jump(afterCatches, expression); builder.exitLexicalScope(catchClause); @@ -794,15 +763,15 @@ public class JetControlFlowProcessor { } @Override - public void visitWhileExpressionVoid(@NotNull JetWhileExpression expression, CFPContext context) { - mark(expression); + public void visitWhileExpression(@NotNull JetWhileExpression expression) { LoopInfo loopInfo = builder.enterLoop(expression, null, null); builder.bindLabel(loopInfo.getConditionEntryPoint()); JetExpression condition = expression.getCondition(); if (condition != null) { - generateInstructions(condition, IN_CONDITION); + generateInstructions(condition); } + mark(expression); boolean conditionIsTrueConstant = CompileTimeConstantUtils.canBeReducedToBooleanConstant(condition, trace, true); if (!conditionIsTrueConstant) { builder.jumpOnFalse(loopInfo.getExitPoint(), expression, builder.getBoundValue(condition)); @@ -811,7 +780,7 @@ public class JetControlFlowProcessor { builder.bindLabel(loopInfo.getBodyEntryPoint()); JetExpression body = expression.getBody(); if (body != null) { - generateInstructions(body, NOT_IN_CONDITION); + generateInstructions(body); } builder.jump(loopInfo.getEntryPoint(), expression); builder.exitLoop(expression); @@ -819,7 +788,7 @@ public class JetControlFlowProcessor { } @Override - public void visitDoWhileExpressionVoid(@NotNull JetDoWhileExpression expression, CFPContext context) { + public void visitDoWhileExpression(@NotNull JetDoWhileExpression expression) { builder.enterLexicalScope(expression); mark(expression); LoopInfo loopInfo = builder.enterLoop(expression, null, null); @@ -827,12 +796,12 @@ public class JetControlFlowProcessor { builder.bindLabel(loopInfo.getBodyEntryPoint()); JetExpression body = expression.getBody(); if (body != null) { - generateInstructions(body, NOT_IN_CONDITION); + generateInstructions(body); } builder.bindLabel(loopInfo.getConditionEntryPoint()); JetExpression condition = expression.getCondition(); if (condition != null) { - generateInstructions(condition, IN_CONDITION); + generateInstructions(condition); } builder.jumpOnTrue(loopInfo.getEntryPoint(), expression, builder.getBoundValue(condition)); builder.exitLoop(expression); @@ -841,13 +810,12 @@ public class JetControlFlowProcessor { } @Override - public void visitForExpressionVoid(@NotNull JetForExpression expression, CFPContext context) { + public void visitForExpression(@NotNull JetForExpression expression) { builder.enterLexicalScope(expression); - mark(expression); JetExpression loopRange = expression.getLoopRange(); if (loopRange != null) { - generateInstructions(loopRange, NOT_IN_CONDITION); + generateInstructions(loopRange); } declareLoopParameter(expression); @@ -863,9 +831,10 @@ public class JetControlFlowProcessor { builder.bindLabel(loopInfo.getBodyEntryPoint()); writeLoopParameterAssignment(expression); + mark(expression); JetExpression body = expression.getBody(); if (body != null) { - generateInstructions(body, NOT_IN_CONDITION); + generateInstructions(body); } builder.nondeterministicJump(loopInfo.getEntryPoint(), expression, null); @@ -891,15 +860,21 @@ public class JetControlFlowProcessor { JetMultiDeclaration multiDeclaration = expression.getMultiParameter(); JetExpression loopRange = expression.getLoopRange(); - JetType loopRangeType = trace.get(BindingContext.EXPRESSION_TYPE, loopRange); - TypePredicate loopRangeTypeSet = loopRangeType != null ? new SingleType(loopRangeType) : AllTypes.instance$; - PseudoValue loopRangeValue = builder.getBoundValue(loopRange); + TypePredicate loopRangeTypePredicate = AllTypes.instance$; + ResolvedCall iteratorResolvedCall = trace.get(BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange); + if (iteratorResolvedCall != null) { + ReceiverValue iteratorReceiver = getExplicitReceiverValue(iteratorResolvedCall); + if (iteratorReceiver.exists()) { + loopRangeTypePredicate = PseudocodePackage.getReceiverTypePredicate(iteratorResolvedCall, iteratorReceiver); + } + } + PseudoValue loopRangeValue = builder.getBoundValue(loopRange); PseudoValue value = builder.magic( loopRange != null ? loopRange : expression, null, Collections.singletonList(loopRangeValue), - Collections.singletonMap(loopRangeValue, loopRangeTypeSet), + Collections.singletonMap(loopRangeValue, loopRangeTypePredicate), true ).getOutputValue(); @@ -913,8 +888,19 @@ public class JetControlFlowProcessor { } } + private ReceiverValue getExplicitReceiverValue(ResolvedCall resolvedCall) { + switch(resolvedCall.getExplicitReceiverKind()) { + case THIS_OBJECT: + return resolvedCall.getThisObject(); + case RECEIVER_ARGUMENT: + return resolvedCall.getReceiverArgument(); + default: + return ReceiverValue.NO_RECEIVER; + } + } + @Override - public void visitBreakExpressionVoid(@NotNull JetBreakExpression expression, CFPContext context) { + public void visitBreakExpression(@NotNull JetBreakExpression expression) { JetElement loop = getCorrespondingLoop(expression); if (loop != null) { checkJumpDoesNotCrossFunctionBoundary(expression, loop); @@ -923,7 +909,7 @@ public class JetControlFlowProcessor { } @Override - public void visitContinueExpressionVoid(@NotNull JetContinueExpression expression, CFPContext context) { + public void visitContinueExpression(@NotNull JetContinueExpression expression) { JetElement loop = getCorrespondingLoop(expression); if (loop != null) { checkJumpDoesNotCrossFunctionBoundary(expression, loop); @@ -966,10 +952,10 @@ public class JetControlFlowProcessor { } @Override - public void visitReturnExpressionVoid(@NotNull JetReturnExpression expression, CFPContext context) { + public void visitReturnExpression(@NotNull JetReturnExpression expression) { JetExpression returnedExpression = expression.getReturnedExpression(); if (returnedExpression != null) { - generateInstructions(returnedExpression, NOT_IN_CONDITION); + generateInstructions(returnedExpression); } JetSimpleNameExpression labelElement = expression.getTargetLabel(); JetElement subroutine; @@ -1001,17 +987,30 @@ public class JetControlFlowProcessor { } @Override - public void visitParameterVoid(@NotNull JetParameter parameter, CFPContext context) { + public void visitParameter(@NotNull JetParameter parameter) { builder.declareParameter(parameter); JetExpression defaultValue = parameter.getDefaultValue(); if (defaultValue != null) { - generateInstructions(defaultValue, context); + Label skipDefaultValue = builder.createUnboundLabel("after default value for parameter " + parameter.getName()); + builder.nondeterministicJump(skipDefaultValue, defaultValue, null); + generateInstructions(defaultValue); + builder.bindLabel(skipDefaultValue); } - generateInitializer(parameter, createSyntheticValue(parameter)); + generateInitializer(parameter, computePseudoValueForParameter(parameter)); + } + + @NotNull + private PseudoValue computePseudoValueForParameter(@NotNull JetParameter parameter) { + PseudoValue syntheticValue = createSyntheticValue(parameter); + PseudoValue defaultValue = builder.getBoundValue(parameter.getDefaultValue()); + if (defaultValue == null) { + return syntheticValue; + } + return builder.merge(parameter, Lists.newArrayList(defaultValue, syntheticValue)).getOutputValue(); } @Override - public void visitBlockExpressionVoid(@NotNull JetBlockExpression expression, CFPContext context) { + public void visitBlockExpression(@NotNull JetBlockExpression expression) { boolean declareLexicalScope = !isBlockInDoWhile(expression); if (declareLexicalScope) { builder.enterLexicalScope(expression); @@ -1019,7 +1018,7 @@ public class JetControlFlowProcessor { mark(expression); List statements = expression.getStatements(); for (JetElement statement : statements) { - generateInstructions(statement, NOT_IN_CONDITION); + generateInstructions(statement); } if (statements.isEmpty()) { builder.loadUnit(expression); @@ -1039,12 +1038,12 @@ public class JetControlFlowProcessor { } @Override - public void visitNamedFunctionVoid(@NotNull JetNamedFunction function, CFPContext context) { + public void visitNamedFunction(@NotNull JetNamedFunction function) { processLocalDeclaration(function); } @Override - public void visitFunctionLiteralExpressionVoid(@NotNull JetFunctionLiteralExpression expression, CFPContext context) { + public void visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression) { mark(expression); JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); processLocalDeclaration(functionLiteral); @@ -1052,44 +1051,43 @@ public class JetControlFlowProcessor { } @Override - public void visitQualifiedExpressionVoid(@NotNull JetQualifiedExpression expression, CFPContext context) { + public void visitQualifiedExpression(@NotNull JetQualifiedExpression expression) { mark(expression); JetExpression selectorExpression = expression.getSelectorExpression(); JetExpression receiverExpression = expression.getReceiverExpression(); // todo: replace with selectorExpresion != null after parser is fixed if (selectorExpression instanceof JetCallExpression || selectorExpression instanceof JetSimpleNameExpression) { - generateInstructions(selectorExpression, NOT_IN_CONDITION); + generateInstructions(selectorExpression); copyValue(selectorExpression, expression); } else { - generateInstructions(receiverExpression, NOT_IN_CONDITION); + generateInstructions(receiverExpression); createNonSyntheticValue(expression, receiverExpression); } } @Override - public void visitCallExpressionVoid(@NotNull JetCallExpression expression, CFPContext context) { - mark(expression); - + public void visitCallExpression(@NotNull JetCallExpression expression) { JetExpression calleeExpression = expression.getCalleeExpression(); - if (!generateCall(expression, calleeExpression)) { + if (!generateCall(calleeExpression, true)) { List inputExpressions = new ArrayList(); for (ValueArgument argument : expression.getValueArguments()) { JetExpression argumentExpression = argument.getArgumentExpression(); if (argumentExpression != null) { - generateInstructions(argumentExpression, NOT_IN_CONDITION); + generateInstructions(argumentExpression); inputExpressions.add(argumentExpression); } } for (JetExpression functionLiteral : expression.getFunctionLiteralArguments()) { - generateInstructions(functionLiteral, NOT_IN_CONDITION); + generateInstructions(functionLiteral); inputExpressions.add(functionLiteral); } - generateInstructions(calleeExpression, NOT_IN_CONDITION); + generateInstructions(calleeExpression); inputExpressions.add(calleeExpression); inputExpressions.add(generateAndGetReceiverIfAny(expression)); + mark(expression); createNonSyntheticValue(expression, inputExpressions); } } @@ -1103,13 +1101,13 @@ public class JetControlFlowProcessor { if (qualifiedExpression.getSelectorExpression() != expression) return null; JetExpression receiverExpression = qualifiedExpression.getReceiverExpression(); - generateInstructions(receiverExpression, NOT_IN_CONDITION); + generateInstructions(receiverExpression); return receiverExpression; } @Override - public void visitPropertyVoid(@NotNull JetProperty property, CFPContext context) { + public void visitProperty(@NotNull JetProperty property) { builder.declareVariable(property); JetExpression initializer = property.getInitializer(); if (initializer != null) { @@ -1117,23 +1115,23 @@ public class JetControlFlowProcessor { } JetExpression delegate = property.getDelegateExpression(); if (delegate != null) { - generateInstructions(delegate, NOT_IN_CONDITION); + generateInstructions(delegate); } if (JetPsiUtil.isLocal(property)) { for (JetPropertyAccessor accessor : property.getAccessors()) { - generateInstructions(accessor, NOT_IN_CONDITION); + generateInstructions(accessor); } } } @Override - public void visitMultiDeclarationVoid(@NotNull JetMultiDeclaration declaration, CFPContext context) { + public void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration) { visitMultiDeclaration(declaration, true); } private void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration, boolean generateWriteForEntries) { JetExpression initializer = declaration.getInitializer(); - generateInstructions(initializer, NOT_IN_CONDITION); + generateInstructions(initializer); for (JetMultiDeclarationEntry entry : declaration.getEntries()) { builder.declareVariable(entry); @@ -1145,7 +1143,7 @@ public class JetControlFlowProcessor { entry, entry, resolvedCall, - getReceiverValues(initializer, resolvedCall, false), + getReceiverValues(resolvedCall, false), Collections.emptyMap() ).getOutputValue(); } @@ -1160,34 +1158,34 @@ public class JetControlFlowProcessor { } @Override - public void visitPropertyAccessorVoid(@NotNull JetPropertyAccessor accessor, CFPContext context) { + public void visitPropertyAccessor(@NotNull JetPropertyAccessor accessor) { processLocalDeclaration(accessor); } @Override - public void visitBinaryWithTypeRHSExpressionVoid(@NotNull JetBinaryExpressionWithTypeRHS expression, CFPContext context) { + public void visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression) { mark(expression); IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); JetExpression left = expression.getLeft(); if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) { - generateInstructions(left, NOT_IN_CONDITION); + generateInstructions(left); copyValue(left, expression); } else { - visitJetElementVoid(expression, context); + visitJetElement(expression); createNonSyntheticValue(expression, left); } } @Override - public void visitThrowExpressionVoid(@NotNull JetThrowExpression expression, CFPContext context) { + public void visitThrowExpression(@NotNull JetThrowExpression expression) { mark(expression); JetExpression thrownExpression = expression.getThrownExpression(); if (thrownExpression == null) return; - generateInstructions(thrownExpression, NOT_IN_CONDITION); + generateInstructions(thrownExpression); PseudoValue thrownValue = builder.getBoundValue(thrownExpression); if (thrownValue == null) return; @@ -1196,29 +1194,29 @@ public class JetControlFlowProcessor { } @Override - public void visitArrayAccessExpressionVoid(@NotNull JetArrayAccessExpression expression, CFPContext context) { + public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) { mark(expression); ResolvedCall getMethodResolvedCall = trace.get(BindingContext.INDEXED_LVALUE_GET, expression); - if (!checkAndGenerateCall(expression, expression, getMethodResolvedCall)) { + if (!checkAndGenerateCall(expression, getMethodResolvedCall, true)) { generateArrayAccess(expression, getMethodResolvedCall); } } @Override - public void visitIsExpressionVoid(@NotNull JetIsExpression expression, CFPContext context) { + public void visitIsExpression(@NotNull JetIsExpression expression) { mark(expression); JetExpression left = expression.getLeftHandSide(); - generateInstructions(left, context); + generateInstructions(left); createNonSyntheticValue(expression, left); } @Override - public void visitWhenExpressionVoid(@NotNull JetWhenExpression expression, CFPContext context) { + public void visitWhenExpression(@NotNull JetWhenExpression expression) { mark(expression); JetExpression subjectExpression = expression.getSubjectExpression(); if (subjectExpression != null) { - generateInstructions(subjectExpression, context); + generateInstructions(subjectExpression); } boolean hasElse = false; @@ -1244,7 +1242,7 @@ public class JetControlFlowProcessor { JetWhenCondition[] conditions = whenEntry.getConditions(); for (int i = 0; i < conditions.length; i++) { JetWhenCondition condition = conditions[i]; - condition.accept(conditionVisitor, context); + condition.accept(conditionVisitor); if (i + 1 < conditions.length) { PseudoValue conditionValue = createSyntheticValue(condition, subjectExpression, condition); builder.nondeterministicJump(bodyLabel, expression, conditionValue); @@ -1264,7 +1262,7 @@ public class JetControlFlowProcessor { builder.bindLabel(bodyLabel); JetExpression whenEntryExpression = whenEntry.getExpression(); if (whenEntryExpression != null) { - generateInstructions(whenEntryExpression, context); + generateInstructions(whenEntryExpression); branches.add(whenEntryExpression); } builder.jump(doneLabel, expression); @@ -1282,28 +1280,28 @@ public class JetControlFlowProcessor { } @Override - public void visitObjectLiteralExpressionVoid(@NotNull JetObjectLiteralExpression expression, CFPContext context) { + public void visitObjectLiteralExpression(@NotNull JetObjectLiteralExpression expression) { mark(expression); JetObjectDeclaration declaration = expression.getObjectDeclaration(); - generateInstructions(declaration, context); + generateInstructions(declaration); builder.createAnonymousObject(expression); } @Override - public void visitObjectDeclarationVoid(@NotNull JetObjectDeclaration objectDeclaration, CFPContext context) { - visitClassOrObject(objectDeclaration, context); + public void visitObjectDeclaration(@NotNull JetObjectDeclaration objectDeclaration) { + visitClassOrObject(objectDeclaration); } @Override - public void visitStringTemplateExpressionVoid(@NotNull JetStringTemplateExpression expression, CFPContext context) { + public void visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression) { mark(expression); List inputExpressions = new ArrayList(); for (JetStringTemplateEntry entry : expression.getEntries()) { if (entry instanceof JetStringTemplateEntryWithExpression) { JetExpression entryExpression = entry.getExpression(); - generateInstructions(entryExpression, NOT_IN_CONDITION); + generateInstructions(entryExpression); inputExpressions.add(entryExpression); } } @@ -1311,67 +1309,67 @@ public class JetControlFlowProcessor { } @Override - public void visitTypeProjectionVoid(@NotNull JetTypeProjection typeProjection, CFPContext context) { + public void visitTypeProjection(@NotNull JetTypeProjection typeProjection) { // TODO : Support Type Arguments. Class object may be initialized at this point"); } @Override - public void visitAnonymousInitializerVoid(@NotNull JetClassInitializer classInitializer, CFPContext context) { - generateInstructions(classInitializer.getBody(), context); + public void visitAnonymousInitializer(@NotNull JetClassInitializer classInitializer) { + generateInstructions(classInitializer.getBody()); } - private void visitClassOrObject(JetClassOrObject classOrObject, CFPContext context) { + private void visitClassOrObject(JetClassOrObject classOrObject) { for (JetDelegationSpecifier specifier : classOrObject.getDelegationSpecifiers()) { - generateInstructions(specifier, context); + generateInstructions(specifier); } List declarations = classOrObject.getDeclarations(); if (classOrObject.isLocal()) { for (JetDeclaration declaration : declarations) { - generateInstructions(declaration, context); + generateInstructions(declaration); } return; } //For top-level and inner classes and objects functions are collected and checked separately. for (JetDeclaration declaration : declarations) { if (declaration instanceof JetProperty || declaration instanceof JetClassInitializer) { - generateInstructions(declaration, context); + generateInstructions(declaration); } } } @Override - public void visitClassVoid(@NotNull JetClass klass, CFPContext context) { + public void visitClass(@NotNull JetClass klass) { List parameters = klass.getPrimaryConstructorParameters(); for (JetParameter parameter : parameters) { - generateInstructions(parameter, context); + generateInstructions(parameter); } - visitClassOrObject(klass, context); + visitClassOrObject(klass); } @Override - public void visitDelegationToSuperCallSpecifierVoid(@NotNull JetDelegatorToSuperCall call, CFPContext context) { + public void visitDelegationToSuperCallSpecifier(@NotNull JetDelegatorToSuperCall call) { List valueArguments = call.getValueArguments(); for (ValueArgument valueArgument : valueArguments) { - generateInstructions(valueArgument.getArgumentExpression(), context); + generateInstructions(valueArgument.getArgumentExpression()); } } @Override - public void visitDelegationByExpressionSpecifierVoid(@NotNull JetDelegatorByExpressionSpecifier specifier, CFPContext context) { - generateInstructions(specifier.getDelegateExpression(), context); + public void visitDelegationByExpressionSpecifier(@NotNull JetDelegatorByExpressionSpecifier specifier) { + generateInstructions(specifier.getDelegateExpression()); } @Override - public void visitJetFileVoid(@NotNull JetFile file, CFPContext context) { + public void visitJetFile(@NotNull JetFile file) { for (JetDeclaration declaration : file.getDeclarations()) { if (declaration instanceof JetProperty) { - generateInstructions(declaration, context); + generateInstructions(declaration); } } } @Override - public void visitJetElementVoid(@NotNull JetElement element, CFPContext context) { + public void visitJetElement(@NotNull JetElement element) { builder.unsupported(element); } @@ -1380,29 +1378,32 @@ public class JetControlFlowProcessor { return trace.get(BindingContext.RESOLVED_CALL, expression); } - private boolean generateCall(JetExpression callExpression, @Nullable JetExpression calleeExpression) { + private boolean generateCall(@Nullable JetExpression calleeExpression, boolean bindResultValue) { if (calleeExpression == null) return false; - return checkAndGenerateCall(callExpression, calleeExpression, getResolvedCall(calleeExpression)); + return checkAndGenerateCall(calleeExpression, getResolvedCall(calleeExpression), bindResultValue); } - private boolean checkAndGenerateCall(JetExpression callExpression, JetExpression calleeExpression, @Nullable ResolvedCall resolvedCall) { + private boolean checkAndGenerateCall(JetExpression calleeExpression, @Nullable ResolvedCall resolvedCall, boolean bindResultValue) { if (resolvedCall == null) { builder.compilationError(calleeExpression, "No resolved call"); return false; } - generateCall(callExpression, calleeExpression, resolvedCall); + generateCall(calleeExpression, resolvedCall); return true; } @NotNull - private InstructionWithValue generateCall(JetExpression callExpression, JetExpression calleeExpression, ResolvedCall resolvedCall) { + private InstructionWithValue generateCall(JetExpression calleeExpression, ResolvedCall resolvedCall) { if (resolvedCall instanceof VariableAsFunctionResolvedCall) { VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall; - return generateCall(callExpression, calleeExpression, variableAsFunctionResolvedCall.getFunctionCall()); + return generateCall(calleeExpression, variableAsFunctionResolvedCall.getFunctionCall()); } + JetElement callElement = resolvedCall.getCall().getCallElement(); + JetExpression callExpression = callElement instanceof JetExpression ? (JetExpression) callElement : null; + CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor(); - Map receivers = getReceiverValues(callExpression, resolvedCall, true); + Map receivers = getReceiverValues(resolvedCall, true); SmartFMap parameterValues = SmartFMap.emptyMap(); for (ValueParameterDescriptor parameterDescriptor : resultingDescriptor.getValueParameters()) { ResolvedValueArgument argument = resolvedCall.getValueArguments().get(parameterDescriptor); @@ -1412,27 +1413,30 @@ public class JetControlFlowProcessor { } if (resultingDescriptor instanceof VariableDescriptor) { + assert callExpression != null + : "Variable-based call without call expression: " + callElement.getText(); assert parameterValues.isEmpty() - : "Variable-based call with non-empty argument list: " + resolvedCall.getCall().getCallElement().getText(); + : "Variable-based call with non-empty argument list: " + callElement.getText(); return builder.readVariable(calleeExpression, callExpression, resolvedCall, receivers); } + mark(resolvedCall.getCall().getCallElement()); return builder.call(calleeExpression, callExpression, resolvedCall, receivers, parameterValues); } @NotNull private Map getReceiverValues( - JetExpression callExpression, ResolvedCall resolvedCall, boolean generateInstructions) { SmartFMap receiverValues = SmartFMap.emptyMap(); - receiverValues = getReceiverValues(callExpression, resolvedCall.getThisObject(), generateInstructions, receiverValues); - receiverValues = getReceiverValues(callExpression, resolvedCall.getReceiverArgument(), generateInstructions, receiverValues); + JetElement callElement = resolvedCall.getCall().getCallElement(); + receiverValues = getReceiverValues(callElement, resolvedCall.getThisObject(), generateInstructions, receiverValues); + receiverValues = getReceiverValues(callElement, resolvedCall.getReceiverArgument(), generateInstructions, receiverValues); return receiverValues; } @NotNull private SmartFMap getReceiverValues( - JetExpression callExpression, + JetElement callElement, ReceiverValue receiver, boolean generateInstructions, SmartFMap receiverValues @@ -1441,13 +1445,13 @@ public class JetControlFlowProcessor { if (receiver instanceof ThisReceiver) { if (generateInstructions) { - receiverValues = receiverValues.plus(createSyntheticValue(callExpression), receiver); + receiverValues = receiverValues.plus(createSyntheticValue(callElement), receiver); } } else if (receiver instanceof ExpressionReceiver) { JetExpression expression = ((ExpressionReceiver) receiver).getExpression(); if (generateInstructions) { - generateInstructions(expression, NOT_IN_CONDITION); + generateInstructions(expression); } PseudoValue receiverPseudoValue = builder.getBoundValue(expression); @@ -1485,7 +1489,7 @@ public class JetControlFlowProcessor { SmartFMap parameterValues) { JetExpression expression = valueArgument.getArgumentExpression(); if (expression != null) { - generateInstructions(expression, NOT_IN_CONDITION); + generateInstructions(expression); PseudoValue argValue = builder.getBoundValue(expression); if (argValue != null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index 26944142c2c..8bafae1e6a1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -124,8 +124,12 @@ public class JetFlowInformationProvider { } public void checkFunction(@Nullable JetType expectedReturnType) { + UnreachableCode unreachableCode = collectUnreachableCode(); + reportUnreachableCode(unreachableCode); - checkDefiniteReturn(expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE); + if (subroutine instanceof JetFunctionLiteral) return; + + checkDefiniteReturn(expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE, unreachableCode); markTailCalls(); } @@ -195,7 +199,7 @@ public class JetFlowInformationProvider { JetElement element = localDeclarationInstruction.getElement(); if (element instanceof JetDeclarationWithBody) { JetDeclarationWithBody localDeclaration = (JetDeclarationWithBody) element; - if (localDeclaration instanceof JetFunctionLiteral) continue; + CallableDescriptor functionDescriptor = (CallableDescriptor) trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, localDeclaration); JetType expectedType = functionDescriptor != null ? functionDescriptor.getReturnType() : null; @@ -208,7 +212,7 @@ public class JetFlowInformationProvider { } } - public void checkDefiniteReturn(final @NotNull JetType expectedReturnType) { + public void checkDefiniteReturn(final @NotNull JetType expectedReturnType, @NotNull final UnreachableCode unreachableCode) { assert subroutine instanceof JetDeclarationWithBody; JetDeclarationWithBody function = (JetDeclarationWithBody) subroutine; @@ -219,11 +223,6 @@ public class JetFlowInformationProvider { final boolean blockBody = function.hasBlockBody(); - final Set rootUnreachableElements = collectUnreachableCode(); - for (JetElement element : rootUnreachableElements) { - trace.report(UNREACHABLE_CODE.on(element)); - } - final boolean[] noReturnError = new boolean[] { false }; for (JetElement returnedExpression : returnedExpressions) { returnedExpression.accept(new JetVisitorVoid() { @@ -240,7 +239,7 @@ public class JetFlowInformationProvider { if (blockBody && !noExpectedType(expectedReturnType) && !KotlinBuiltIns.getInstance().isUnit(expectedReturnType) - && !rootUnreachableElements.contains(element)) { + && !unreachableCode.getElements().contains(element)) { noReturnError[0] = true; } } @@ -251,17 +250,25 @@ public class JetFlowInformationProvider { } } - private Set collectUnreachableCode() { - Collection unreachableElements = Lists.newArrayList(); - for (Instruction deadInstruction : pseudocode.getDeadInstructions()) { - if (!(deadInstruction instanceof JetElementInstruction) - || deadInstruction instanceof LoadUnitValueInstruction - || deadInstruction instanceof MergeInstruction - || (deadInstruction instanceof MagicInstruction && ((MagicInstruction) deadInstruction).getSynthetic())) continue; + private void reportUnreachableCode(@NotNull UnreachableCode unreachableCode) { + for (JetElement element : unreachableCode.getElements()) { + trace.report(UNREACHABLE_CODE.on(element, unreachableCode.getUnreachableTextRanges(element))); + } + } - JetElement element = ((JetElementInstruction) deadInstruction).getElement(); + @NotNull + private UnreachableCode collectUnreachableCode() { + Set reachableElements = Sets.newHashSet(); + Set unreachableElements = Sets.newHashSet(); + for (Instruction instruction : pseudocode.getInstructionsIncludingDeadCode()) { + if (!(instruction instanceof JetElementInstruction) + || instruction instanceof LoadUnitValueInstruction + || instruction instanceof MergeInstruction + || (instruction instanceof MagicInstruction && ((MagicInstruction) instruction).getSynthetic())) continue; - if (deadInstruction instanceof JumpInstruction) { + JetElement element = ((JetElementInstruction) instruction).getElement(); + + if (instruction instanceof JumpInstruction) { boolean isJumpElement = element instanceof JetBreakExpression || element instanceof JetContinueExpression || element instanceof JetReturnExpression @@ -269,10 +276,14 @@ public class JetFlowInformationProvider { if (!isJumpElement) continue; } - unreachableElements.add(element); + if (instruction.getDead()) { + unreachableElements.add(element); + } + else { + reachableElements.add(element); + } } - // This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well - return JetPsiUtil.findRootExpressions(unreachableElements); + return new UnreachableCodeImpl(reachableElements, unreachableElements); } //////////////////////////////////////////////////////////////////////////////// diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.kt index 892aea97202..d6a40033efa 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.kt @@ -181,18 +181,10 @@ fun traverseFollowingInstructions( while (!stack.isEmpty()) { val instruction = stack.pop() - visited.add(instruction) + if (!visited.add(instruction)) continue + if (handler != null && !handler(instruction)) return false - val followingInstructions = instruction.getNextInstructions(order) - - for (followingInstruction in followingInstructions) { - if (!visited.contains(followingInstruction)) { - if (handler != null && !handler(instruction)) { - return false - } - stack.push(followingInstruction) - } - } + instruction.getNextInstructions(order).forEach { stack.push(it) } } return true } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/UnreachableCode.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/UnreachableCode.kt new file mode 100644 index 00000000000..b1597d88feb --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/UnreachableCode.kt @@ -0,0 +1,122 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.cfg + +import org.jetbrains.jet.lang.psi.JetElement +import com.intellij.openapi.util.TextRange +import java.util.HashSet +import org.jetbrains.jet.lang.psi.JetPsiUtil +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiElementVisitor +import com.intellij.psi.PsiWhiteSpace +import java.util.ArrayList +import org.jetbrains.jet.lexer.JetTokens +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.psi.PsiComment + +trait UnreachableCode { + val elements: Set + fun getUnreachableTextRanges(element: JetElement): List +} + +class UnreachableCodeImpl( + private val reachableElements: Set, + private val unreachableElements: Set +) : UnreachableCode { + + // This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well + override val elements = JetPsiUtil.findRootExpressions(unreachableElements) + + override fun getUnreachableTextRanges(element: JetElement): List { + return if (element.hasChildrenInSet(reachableElements)) { + element.getLeavesOrReachableChildren().removeReachableElementsWithMeaninglessSiblings().mergeAdjacentTextRanges() + } + else { + listOf(element.getTextRange()!!) + } + } + + private fun JetElement.hasChildrenInSet(set: Set): Boolean { + return PsiTreeUtil.collectElements(this) { it != this }.any { it in set } + } + + private fun JetElement.getLeavesOrReachableChildren(): List { + val children = ArrayList() + acceptChildren(object : PsiElementVisitor() { + override fun visitElement(element: PsiElement) { + val isReachable = element is JetElement && reachableElements.contains(element) && !element.hasChildrenInSet(unreachableElements) + if (isReachable || element.getChildren().size == 0) { + children.add(element) + } + else { + element.acceptChildren(this) + } + } + }) + return children + } + + fun List.removeReachableElementsWithMeaninglessSiblings(): List { + fun PsiElement.isMeaningless() = this is PsiWhiteSpace + || this.getNode()?.getElementType() == JetTokens.COMMA + || this is PsiComment + + val childrenToRemove = HashSet() + fun collectSiblingsIfMeaningless(elementIndex: Int, direction: Int) { + val index = elementIndex + direction + if (index !in 0..(size() - 1)) return + + val element = this[index] + if (element.isMeaningless()) { + childrenToRemove.add(element) + collectSiblingsIfMeaningless(index, direction) + } + } + for ((index, element) in this.withIndices()) { + if (reachableElements.contains(element)) { + childrenToRemove.add(element) + collectSiblingsIfMeaningless(index, -1) + collectSiblingsIfMeaningless(index, 1) + } + } + return this.filter { it !in childrenToRemove } + } + + + private fun List.mergeAdjacentTextRanges(): List { + val result = ArrayList() + val lastRange = fold(null: TextRange?) { + currentTextRange, element -> + + val elementRange = element.getTextRange()!! + if (currentTextRange == null) { + elementRange + } + else if (currentTextRange.getEndOffset() == elementRange.getStartOffset()) { + currentTextRange.union(elementRange) + } + else { + result.add(currentTextRange) + elementRange + } + } + if (lastRange != null) { + result.add(lastRange) + } + return result + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java index e86b008fd7d..91044d06959 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java @@ -45,7 +45,7 @@ public interface Pseudocode { List getReversedInstructions(); @NotNull - List getDeadInstructions(); + List getInstructionsIncludingDeadCode(); @NotNull SubroutineExitInstruction getExitInstruction(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java index 650d9123af3..7452157936e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java @@ -183,30 +183,10 @@ public class PseudocodeImpl implements Pseudocode { return Lists.newArrayList(traversedInstructions); } - //for tests only - @NotNull - public List getAllInstructions() { - return mutableInstructionList; - } - @Override @NotNull - public List getDeadInstructions() { - List deadInstructions = Lists.newArrayList(); - for (Instruction instruction : mutableInstructionList) { - if (isDead(instruction)) { - deadInstructions.add(instruction); - } - } - return deadInstructions; - } - - private static boolean isDead(@NotNull Instruction instruction) { - if (!((InstructionImpl)instruction).getDead()) return false; - for (Instruction copy : instruction.getCopies()) { - if (!((InstructionImpl)copy).getDead()) return false; - } - return true; + public List getInstructionsIncludingDeadCode() { + return mutableInstructionList; } //for tests only @@ -390,7 +370,7 @@ public class PseudocodeImpl implements Pseudocode { Set instructionSet = Sets.newHashSet(instructions); for (Instruction instruction : mutableInstructionList) { if (!instructionSet.contains(instruction)) { - ((InstructionImpl)instruction).die(); + ((InstructionImpl)instruction).setMarkedAsDead(true); for (Instruction nextInstruction : instruction.getNextInstructions()) { nextInstruction.getPreviousInstructions().remove(instruction); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt index ac4bd2030cb..04b8eb99a64 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt @@ -28,16 +28,52 @@ public trait TypePredicate: (JetType) -> Boolean { } public data class SingleType(val targetType: JetType): TypePredicate { - override fun invoke(typeToCheck: JetType): Boolean = JetTypeChecker.INSTANCE.equalTypes(typeToCheck, targetType) + override fun invoke(typeToCheck: JetType): Boolean = JetTypeChecker.DEFAULT.equalTypes(typeToCheck, targetType) override fun toString(): String = targetType.render() } +public data class AllSubtypes(val upperBound: JetType): TypePredicate { + override fun invoke(typeToCheck: JetType): Boolean = JetTypeChecker.DEFAULT.isSubtypeOf(typeToCheck, upperBound) + + override fun toString(): String = "{<: ${upperBound.render()}}" +} + +public data class ForAllTypes(val typeSets: List): TypePredicate { + override fun invoke(typeToCheck: JetType): Boolean = typeSets.all { it(typeToCheck) } + + override fun toString(): String = "AND{${typeSets.makeString(", ")}}" +} + +public data class ForSomeType(val typeSets: List): TypePredicate { + override fun invoke(typeToCheck: JetType): Boolean = typeSets.any { it(typeToCheck) } + + override fun toString(): String = "OR{${typeSets.makeString(", ")}}" +} + public object AllTypes : TypePredicate { override fun invoke(typeToCheck: JetType): Boolean = true - override fun toString(): String = "" + override fun toString(): String = "*" } +// todo: simplify computed type predicate when possible +fun and(predicates: Collection): TypePredicate = + when (predicates.size) { + 0 -> AllTypes + 1 -> predicates.first() + else -> ForAllTypes(predicates.toList()) + } + +fun or(predicates: Collection): TypePredicate? = + when (predicates.size) { + 0 -> null + 1 -> predicates.first() + else -> ForSomeType(predicates.toList()) + } + +fun JetType.getSubtypesPredicate(): TypePredicate? = + if (TypeUtils.canHaveSubtypes(JetTypeChecker.DEFAULT, this)) AllSubtypes(this) else SingleType(this) + private fun JetType.render(): String = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(this) public fun TypePredicate.expectedTypeFor(keys: Iterable): Map = diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/Instruction.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/Instruction.kt index 17fbcaaeffe..ea2df5fbe4e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/Instruction.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/Instruction.kt @@ -23,14 +23,16 @@ import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue public trait Instruction { public var owner: Pseudocode - public val previousInstructions: MutableCollection + public val previousInstructions: Collection public val nextInstructions: Collection + public val dead: Boolean + public val lexicalScope: LexicalScope public val inputValues: List - public fun getCopies(): Collection + public val copies: Collection public fun accept(visitor: InstructionVisitor) public fun accept(visitor: InstructionVisitorWithResult): R diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionImpl.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionImpl.kt index bb367a57f1b..3318a932b83 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionImpl.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionImpl.kt @@ -25,39 +25,6 @@ import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue public abstract class InstructionImpl(public override val lexicalScope: LexicalScope): Instruction { private var _owner: Pseudocode? = null - private val _copies = HashSet() - private var original: Instruction? = null - protected var _dead: Boolean = false - - private fun setOriginalInstruction(value: Instruction?) { - assert(original == null) { "Instruction can't have two originals: this.original = ${original}; new original = $this" } - original = value - } - - protected fun outgoingEdgeTo(target: Instruction?): Instruction? { - if (target != null) { - target.previousInstructions.add(this) - } - return target - } - - protected fun updateCopyInfo(instruction: InstructionImpl): Instruction { - _copies.add(instruction) - instruction.setOriginalInstruction(this) - return instruction - } - - protected abstract fun createCopy(): InstructionImpl - - public fun die() { - _dead = true - } - - public val dead: Boolean get() = _dead - - public fun copy(): Instruction { - return updateCopyInfo(createCopy()) - } override var owner: Pseudocode get() = _owner!! @@ -66,16 +33,34 @@ public abstract class InstructionImpl(public override val lexicalScope: LexicalS _owner = value } + private var allCopies: MutableSet? = null + + override val copies: Collection + get() = allCopies?.filter { it != this } ?: Collections.emptyList() + + fun copy(): Instruction = updateCopyInfo(createCopy()) + + protected abstract fun createCopy(): InstructionImpl + + protected fun updateCopyInfo(instruction: InstructionImpl): Instruction { + if (allCopies == null) { + allCopies = hashSetOf(this) + } + instruction.allCopies = allCopies + allCopies!!.add(instruction) + return instruction + } + + public var markedAsDead: Boolean = false + + override val dead: Boolean get() = allCopies?.all { it.markedAsDead } ?: markedAsDead + override val previousInstructions: MutableCollection = LinkedHashSet() - override val inputValues: List = Collections.emptyList() - - override fun getCopies(): Collection { - return original?.let { original -> - val originalCopies = Sets.newHashSet(original.getCopies()) - originalCopies.remove(this) - originalCopies.add(original) - originalCopies - } ?: _copies + protected fun outgoingEdgeTo(target: Instruction?): Instruction? { + (target as InstructionImpl?)?.previousInstructions?.add(this) + return target } + + override val inputValues: List = Collections.emptyList() } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt index 01871a57938..41e3886f47b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt @@ -16,13 +16,21 @@ package org.jetbrains.jet.lang.cfg.pseudocode -import org.jetbrains.jet.lang.psi.JetExpression -import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.traverseFollowingInstructions -import java.util.HashSet -import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.TraversalOrder -import org.jetbrains.jet.lang.psi.JetFunction -import org.jetbrains.jet.lang.psi.psiUtil.getParentByType -import org.jetbrains.jet.lang.psi.JetFunctionLiteral +import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.* +import org.jetbrains.jet.lang.cfg.pseudocode.instructions.* +import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.* +import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.* +import org.jetbrains.jet.lang.psi.* +import org.jetbrains.jet.lang.descriptors.* +import org.jetbrains.jet.lang.resolve.bindingContextUtil.* +import org.jetbrains.jet.lang.resolve.calls.model.* +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns +import org.jetbrains.jet.lang.resolve.BindingContext +import java.util.* +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.jet.lang.resolve.OverridingUtil +import org.jetbrains.jet.lang.types.TypeUtils +import org.jetbrains.jet.lang.types.JetType fun JetExpression.isStatement(pseudocode: Pseudocode): Boolean { val value = pseudocode.getElementValue(this); @@ -32,7 +40,7 @@ fun JetExpression.isStatement(pseudocode: Pseudocode): Boolean { return when { (getParent() as? JetFunction)?.getBodyExpression() == this -> true - pseudocode.getElementValue(getParentByType(javaClass())?.getBodyExpression()) == value -> + value.implicitReturnValue -> true else -> false @@ -42,4 +50,127 @@ fun JetExpression.isStatement(pseudocode: Pseudocode): Boolean { val instruction = value.createdAt if (considerUsedIfCreatedBeforeExit() && instruction.nextInstructions.any { it == pseudocode.getExitInstruction() }) return false return traverseFollowingInstructions(instruction, HashSet(), TraversalOrder.FORWARD) { value !in it.inputValues } +} + +val PseudoValue.implicitReturnValue: Boolean + get() { + val pseudocode = createdAt.owner + + val function = pseudocode.getCorrespondingElement() as? JetDeclarationWithBody + + if (function is JetFunctionLiteral || (function != null && !function.hasBlockBody())) { + return pseudocode.getElementValue(function.getBodyExpression()) == this + } + return false + } + +fun Pseudocode.collectValueUsages(): Map> { + val map = HashMap>() + traverseFollowingInstructions(getEnterInstruction(), HashSet(), TraversalOrder.FORWARD) { + for (value in it.inputValues) { + map.getOrPut(value){ ArrayList() }.add(it) + } + true + } + + return map +} + +fun getReceiverTypePredicate(resolvedCall: ResolvedCall<*>, receiverValue: ReceiverValue): TypePredicate? { + val callableDescriptor = resolvedCall.getResultingDescriptor() + if (callableDescriptor == null) return null + + when (receiverValue) { + resolvedCall.getReceiverArgument() -> { + val receiverParameter = callableDescriptor.getReceiverParameter() + if (receiverParameter != null) return receiverParameter.getType().getSubtypesPredicate() + } + resolvedCall.getThisObject() -> { + val rootCallableDescriptors = OverridingUtil.getTopmostOverridenDescriptors(callableDescriptor) + return or(rootCallableDescriptors.map { + it.getExpectedThisObject()?.getType()?.let { TypeUtils.makeNullableIfNeeded(it, resolvedCall.isSafeCall()) }?.getSubtypesPredicate() + }.filterNotNull()) + } + } + + return null +} + +fun getExpectedTypePredicate( + value: PseudoValue, + valueUsageMap: Map>, + bindingContext: BindingContext +): TypePredicate { + val typePredicates = HashSet() + + fun addSubtypesOf(jetType: JetType?) = typePredicates.add(jetType?.getSubtypesPredicate()) + + fun addTypePredicates(value: PseudoValue) { + if (value.implicitReturnValue) { + val function = value.createdAt.owner.getCorrespondingElement() as? JetDeclarationWithBody + val functionDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, function] as? FunctionDescriptor + addSubtypesOf(functionDescriptor?.getReturnType()) + } + + valueUsageMap[value]?.forEach { + when (it) { + is ReturnValueInstruction -> { + val functionDescriptor = (it.element as JetReturnExpression).getTargetFunctionDescriptor(bindingContext) + addSubtypesOf(functionDescriptor?.getReturnType()) + } + + is ConditionalJumpInstruction -> + addSubtypesOf(KotlinBuiltIns.getInstance().getBooleanType()) + + is ThrowExceptionInstruction -> + addSubtypesOf(KotlinBuiltIns.getInstance().getThrowable().getDefaultType()) + + is MergeInstruction -> + addTypePredicates(it.outputValue) + + is AccessValueInstruction -> { + val accessTarget = it.target + val receiverValue = it.receiverValues[value] + if (receiverValue != null) { + typePredicates.add(getReceiverTypePredicate((accessTarget as AccessTarget.Call).resolvedCall, receiverValue)) + } + else { + val expectedType = when (accessTarget) { + is AccessTarget.Call -> + (accessTarget.resolvedCall.getResultingDescriptor() as? VariableDescriptor)?.getType() + is AccessTarget.Declaration -> + accessTarget.descriptor.getType() + else -> + null + } + addSubtypesOf(expectedType) + } + } + + is CallInstruction -> { + val receiverValue = it.receiverValues[value] + if (receiverValue != null) { + typePredicates.add(getReceiverTypePredicate(it.resolvedCall, receiverValue)) + } + else { + it.arguments[value]?.let { parameter -> + val expectedType = when (it.resolvedCall.getValueArguments()[parameter]) { + is VarargValueArgument -> + parameter.getVarargElementType() + else -> + parameter.getType() + } + addSubtypesOf(expectedType) + } + } + } + + is MagicInstruction -> + typePredicates.add(it.expectedTypes[value]) + } + } + } + + addTypePredicates(value) + return and(typePredicates.filterNotNull()) } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnostic.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnostic.java index 598049b6c5a..8616757045f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnostic.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnostic.java @@ -27,6 +27,7 @@ public abstract class AbstractDiagnostic implements Parame private final E psiElement; private final DiagnosticFactoryWithPsiElement factory; private final Severity severity; + private List textRanges; public AbstractDiagnostic(@NotNull E psiElement, @NotNull DiagnosticFactoryWithPsiElement factory, @@ -63,6 +64,9 @@ public abstract class AbstractDiagnostic implements Parame @Override @NotNull public List getTextRanges() { + if (textRanges != null) { + return textRanges; + } return getFactory().getTextRanges(this); } @@ -71,4 +75,10 @@ public abstract class AbstractDiagnostic implements Parame if (!getFactory().isValid(this)) return false; return true; } + + @NotNull + public Diagnostic setTextRanges(@NotNull List textRanges) { + this.textRanges = textRanges; + return this; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement.java index 5a01175740d..a015899f523 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement.java @@ -30,7 +30,7 @@ public abstract class DiagnosticFactoryWithPsiElement getTextRanges(ParametrizedDiagnostic diagnostic) { - return positioningStrategy.mark(diagnostic.getPsiElement()); + return positioningStrategy.markDiagnostic(diagnostic); } protected boolean isValid(ParametrizedDiagnostic diagnostic) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 3d0df53cdf9..1620da3f528 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -17,9 +17,11 @@ package org.jetbrains.jet.lang.diagnostics; import com.google.common.collect.ImmutableSet; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNameIdentifierOwner; import com.intellij.psi.impl.source.tree.LeafPsiElement; +import kotlin.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; @@ -446,7 +448,13 @@ public interface Errors { // Control flow / Data flow - DiagnosticFactory0 UNREACHABLE_CODE = DiagnosticFactory0.create(WARNING); + DiagnosticFactory1> UNREACHABLE_CODE = DiagnosticFactory1.create( + WARNING, PositioningStrategies.markTextRangesFromDiagnostic(new Function1>() { + @Override + public List invoke(Diagnostic diagnostic) { + return UNREACHABLE_CODE.cast(diagnostic).getA(); + } + })); DiagnosticFactory0 VARIABLE_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, NAME_IDENTIFIER); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java index b472dd4169c..a0e5d07199c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java @@ -23,6 +23,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNameIdentifierOwner; +import kotlin.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.lang.psi.*; @@ -527,6 +528,18 @@ public class PositioningStrategies { } }; + public static PositioningStrategy markTextRangesFromDiagnostic( + @NotNull final Function1> getTextRanges + ) { + return new PositioningStrategy() { + @NotNull + @Override + public List markDiagnostic(@NotNull ParametrizedDiagnostic diagnostic) { + return getTextRanges.invoke(diagnostic); + } + }; + } + private PositioningStrategies() { } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.java index a149ef32b69..16486f78e7a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.java @@ -27,7 +27,12 @@ import java.util.List; public class PositioningStrategy { @NotNull - public List mark(@NotNull E element) { + public List markDiagnostic(@NotNull ParametrizedDiagnostic diagnostic) { + return mark(diagnostic.getPsiElement()); + } + + @NotNull + protected List mark(@NotNull E element) { return markElement(element); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java index deace52941b..bb804680559 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java @@ -212,7 +212,7 @@ public class DefaultErrorMessages { MAP.put(INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER, "Setter of this property can be overridden, so initialization using backing field required", NAME); - MAP.put(UNREACHABLE_CODE, "Unreachable code"); + MAP.put(UNREACHABLE_CODE, "Unreachable code", TO_STRING); MAP.put(MANY_CLASS_OBJECTS, "Only one class object is allowed per class"); MAP.put(CLASS_OBJECT_NOT_ALLOWED, "A class object is not allowed here"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java index 0bf808a306e..72d3d2b52da 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java @@ -229,13 +229,13 @@ public class Renderers { parameterTypes.add(valueParameterDescriptor.getType()); if (valueParameterDescriptor.getIndex() >= inferenceErrorData.valueArgumentsTypes.size()) continue; JetType actualType = inferenceErrorData.valueArgumentsTypes.get(valueParameterDescriptor.getIndex()); - if (!JetTypeChecker.INSTANCE.isSubtypeOf(actualType, valueParameterDescriptor.getType())) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(actualType, valueParameterDescriptor.getType())) { errorPositions.add(ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex())); } } if (receiverType != null && inferenceErrorData.receiverArgumentType != null && - !JetTypeChecker.INSTANCE.isSubtypeOf(inferenceErrorData.receiverArgumentType, receiverType)) { + !JetTypeChecker.DEFAULT.isSubtypeOf(inferenceErrorData.receiverArgumentType, receiverType)) { errorPositions.add(ConstraintPosition.RECEIVER_POSITION); } @@ -333,7 +333,7 @@ public class Renderers { JetType upperBoundWithSubstitutedInferredTypes = systemWithoutWeakConstraints.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT); if (upperBoundWithSubstitutedInferredTypes != null && - !JetTypeChecker.INSTANCE.isSubtypeOf(inferredValueForTypeParameter, upperBoundWithSubstitutedInferredTypes)) { + !JetTypeChecker.DEFAULT.isSubtypeOf(inferredValueForTypeParameter, upperBoundWithSubstitutedInferredTypes)) { violatedUpperBound = upperBoundWithSubstitutedInferredTypes; break; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 9e81e05b271..1c6dbfb32d7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -780,13 +780,13 @@ public class JetExpressionParsing extends AbstractJetParsing { // Parse when block myBuilder.enableNewlines(); - expect(LBRACE, "Expecting '{'"); + if (expect(LBRACE, "Expecting '{'")) { + while (!eof() && !at(RBRACE)) { + parseWhenEntry(); + } - while (!eof() && !at(RBRACE)) { - parseWhenEntry(); + expect(RBRACE, "Expecting '}'"); } - - expect(RBRACE, "Expecting '}'"); myBuilder.restoreNewlinesState(); when.done(WHEN); @@ -1370,35 +1370,40 @@ public class JetExpressionParsing extends AbstractJetParsing { advance(); // FOR_KEYWORD - myBuilder.disableNewlines(); - expect(LPAR, "Expecting '(' to open a loop range", TokenSet.create(RPAR, VAL_KEYWORD, VAR_KEYWORD, IDENTIFIER)); + if (expect(LPAR, "Expecting '(' to open a loop range", EXPRESSION_FIRST)) { + myBuilder.disableNewlines(); - PsiBuilder.Marker parameter = mark(); - if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD - if (at(LPAR)) { - myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE)); + if (!at(RPAR)) { + PsiBuilder.Marker parameter = mark(); + if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD + if (at(LPAR)) { + myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE)); + parameter.done(MULTI_VARIABLE_DECLARATION); + } + else { + expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON, IN_KEYWORD)); - parameter.done(MULTI_VARIABLE_DECLARATION); - } - else { - expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON)); + if (at(COLON)) { + advance(); // COLON + myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD)); + } + parameter.done(VALUE_PARAMETER); + } - if (at(COLON)) { - advance(); // COLON - myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD)); + if (expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE, RPAR))) { + PsiBuilder.Marker range = mark(); + parseExpression(); + range.done(LOOP_RANGE); + } } - parameter.done(VALUE_PARAMETER); + else { + error("Expecting a variable name"); + } + + expectNoAdvance(RPAR, "Expecting ')'"); + myBuilder.restoreNewlinesState(); } - expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE)); - - PsiBuilder.Marker range = mark(); - parseExpression(); - range.done(LOOP_RANGE); - - expectNoAdvance(RPAR, "Expecting ')'"); - myBuilder.restoreNewlinesState(); - parseControlStructureBody(); loop.done(FOR); @@ -1548,13 +1553,14 @@ public class JetExpressionParsing extends AbstractJetParsing { */ private void parseCondition() { myBuilder.disableNewlines(); - expect(LPAR, "Expecting a condition in parentheses '(...)'"); - PsiBuilder.Marker condition = mark(); - parseExpression(); - condition.done(CONDITION); + if (expect(LPAR, "Expecting a condition in parentheses '(...)'", EXPRESSION_FIRST)) { + PsiBuilder.Marker condition = mark(); + parseExpression(); + condition.done(CONDITION); + expect(RPAR, "Expecting ')"); + } - expect(RPAR, "Expecting ')"); myBuilder.restoreNewlinesState(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetDoWhileExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetDoWhileExpression.java index bbd431f232c..9c40ea72366 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetDoWhileExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetDoWhileExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * Copyright 2010-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,10 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lexer.JetTokens; public class JetDoWhileExpression extends JetWhileExpressionBase { public JetDoWhileExpression(@NotNull ASTNode node) { @@ -28,4 +31,11 @@ public class JetDoWhileExpression extends JetWhileExpressionBase { public R accept(@NotNull JetVisitor visitor, D data) { return visitor.visitDoWhileExpression(this, data); } + + @Nullable + @IfNotParsed + public PsiElement getWhileKeywordElement() { + //noinspection ConstantConditions + return findChildByType(JetTokens.WHILE_KEYWORD); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetIfExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetIfExpression.java index ca97a616510..d166b46d261 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetIfExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetIfExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * Copyright 2010-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,9 +17,11 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; +import org.jetbrains.jet.lexer.JetTokens; public class JetIfExpression extends JetExpressionImpl { public JetIfExpression(@NotNull ASTNode node) { @@ -36,6 +38,16 @@ public class JetIfExpression extends JetExpressionImpl { return findExpressionUnder(JetNodeTypes.CONDITION); } + @Nullable @IfNotParsed + public PsiElement getLeftParenthesis() { + return findChildByType(JetTokens.LPAR); + } + + @Nullable @IfNotParsed + public PsiElement getRightParenthesis() { + return findChildByType(JetTokens.RPAR); + } + @Nullable public JetExpression getThen() { return findExpressionUnder(JetNodeTypes.THEN); @@ -45,4 +57,9 @@ public class JetIfExpression extends JetExpressionImpl { public JetExpression getElse() { return findExpressionUnder(JetNodeTypes.ELSE); } + + @Nullable + public PsiElement getElseKeyword() { + return findChildByType(JetTokens.ELSE_KEYWORD); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetLoopExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetLoopExpression.java index 0f86e062358..9cab172d203 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetLoopExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetLoopExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * Copyright 2010-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,9 +17,11 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; +import org.jetbrains.jet.lexer.JetTokens; public abstract class JetLoopExpression extends JetExpressionImpl implements JetStatementExpression { public JetLoopExpression(@NotNull ASTNode node) { @@ -30,4 +32,15 @@ public abstract class JetLoopExpression extends JetExpressionImpl implements Jet public JetExpression getBody() { return findExpressionUnder(JetNodeTypes.BODY); } + + @Nullable + @IfNotParsed + public PsiElement getLeftParenthesis() { + return findChildByType(JetTokens.LPAR); + } + + @Nullable @IfNotParsed + public PsiElement getRightParenthesis() { + return findChildByType(JetTokens.RPAR); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java index 59d6e08d1b4..74de6355425 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * Copyright 2010-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,13 +47,28 @@ public class JetWhenExpression extends JetExpressionImpl { @NotNull public PsiElement getWhenKeywordElement() { + //noinspection ConstantConditions return findChildByType(JetTokens.WHEN_KEYWORD); } @Nullable - public PsiElement getCloseBraceNode() { - ASTNode openBraceNode = getNode().findChildByType(JetTokens.RBRACE); - return openBraceNode != null ? openBraceNode.getPsi() : null; + public PsiElement getCloseBrace() { + return findChildByType(JetTokens.RBRACE); + } + + @Nullable + public PsiElement getOpenBrace() { + return findChildByType(JetTokens.LBRACE); + } + + @Nullable + public PsiElement getLeftParenthesis() { + return findChildByType(JetTokens.LPAR); + } + + @Nullable + public PsiElement getRightParenthesis() { + return findChildByType(JetTokens.RPAR); } @Nullable diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhileExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhileExpression.java index 8f9218064a6..c8fa88df31a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhileExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhileExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * Copyright 2010-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileElementType.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileElementType.java index 602fc439e60..6addb68814f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileElementType.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileElementType.java @@ -36,7 +36,7 @@ import org.jetbrains.jet.plugin.JetLanguage; import java.io.IOException; public class JetFileElementType extends IStubFileElementType { - public static final int STUB_VERSION = 28; + public static final int STUB_VERSION = 29; public JetFileElementType() { super("jet.FILE", JetLanguage.INSTANCE); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementType.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementType.java index cac012ab8a3..fea9bfacc72 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementType.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementType.java @@ -23,13 +23,14 @@ import com.intellij.psi.stubs.IndexSink; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IStubFileElementType; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ArrayFactory; -import com.intellij.util.ArrayUtil; import com.intellij.util.ReflectionUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.psi.JetClassOrObject; +import org.jetbrains.jet.lang.psi.JetElementImplStub; +import org.jetbrains.jet.lang.psi.JetFunction; +import org.jetbrains.jet.lang.psi.JetProperty; import org.jetbrains.jet.plugin.JetLanguage; import java.lang.reflect.Array; @@ -37,9 +38,6 @@ import java.lang.reflect.Constructor; public abstract class JetStubElementType> extends IStubElementType { - @SuppressWarnings("unchecked") - private static final Class[] ALWAYS_CREATE_STUB_FOR = new Class[] { JetClass.class, JetObjectDeclaration.class }; - @NotNull private final Constructor byNodeConstructor; @NotNull @@ -93,11 +91,14 @@ public abstract class JetStubElementType[] stopAt = ArrayUtil.append(ALWAYS_CREATE_STUB_FOR, JetBlockExpression.class); - @SuppressWarnings("unchecked") JetWithExpressionInitializer withInitializer = - PsiTreeUtil.getParentOfType(declaration, JetWithExpressionInitializer.class, true, stopAt); - if (withInitializer != null) { - JetExpression initializer = withInitializer.getInitializer(); - if (PsiTreeUtil.isAncestor(initializer, declaration, true)) { - return false; - } - } - - // Don't create stubs if declaration is inside property delegate - @SuppressWarnings("unchecked") JetPropertyDelegate delegate = PsiTreeUtil.getParentOfType(declaration, JetPropertyDelegate.class, true, stopAt); - if (delegate != null) { - JetExpression delegateExpression = delegate.getExpression(); - if (PsiTreeUtil.isAncestor(delegateExpression, declaration, true)) { - return false; - } - } - - return true; - } - @Override public void indexStub(@NotNull StubT stub, @NotNull IndexSink sink) { // do not force inheritors to implement this method diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt index 2ab6943670f..1841ed6dfd7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt @@ -21,14 +21,18 @@ import org.jetbrains.jet.lang.psi.Call import org.jetbrains.jet.lang.psi.JetPsiUtil import org.jetbrains.jet.lang.psi.JetCallExpression import org.jetbrains.jet.lang.psi.JetQualifiedExpression -import org.jetbrains.jet.lang.psi.JetBinaryExpression -import org.jetbrains.jet.lang.psi.JetUnaryExpression -import org.jetbrains.jet.lang.psi.JetArrayAccessExpression import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.lang.psi.JetOperationExpression import org.jetbrains.jet.lang.resolve.BindingContext.CALL -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.jet.lang.psi.JetSimpleNameExpression +import org.jetbrains.jet.lang.psi.JetReturnExpression +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor +import org.jetbrains.jet.lang.resolve.BindingContext.LABEL_TARGET +import org.jetbrains.jet.lang.resolve.BindingContext.FUNCTION +import org.jetbrains.jet.lang.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR +import org.jetbrains.jet.lang.psi.psiUtil.getParentByType +import org.jetbrains.jet.lang.psi.JetDeclarationWithBody +import org.jetbrains.jet.lang.resolve.DescriptorUtils +import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor /** * For expressions like a(), a[i], a.b.c(), +a, a + b, (a()), a(): Int, @label a() @@ -51,3 +55,16 @@ fun JetExpression.getCorrespondingCall(bindingContext: BindingContext): Call? { } return bindingContext[CALL, reference] } + +public fun JetReturnExpression.getTargetFunctionDescriptor(bindingContext: BindingContext): FunctionDescriptor? { + val targetLabel = getTargetLabel() + if (targetLabel != null) return bindingContext[LABEL_TARGET, targetLabel]?.let { bindingContext[FUNCTION, it] } + + val declarationDescriptor = bindingContext[DECLARATION_TO_DESCRIPTOR, getParentByType(javaClass())] + val containingFunctionDescriptor = DescriptorUtils.getParentOfType(declarationDescriptor, javaClass(), false) + if (containingFunctionDescriptor == null) return null + + return stream(containingFunctionDescriptor) { DescriptorUtils.getParentOfType(it, javaClass()) } + .dropWhile { it is AnonymousFunctionDescriptor } + .firstOrNull() +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java index a07420658a7..8c4c3bd712c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java @@ -220,13 +220,13 @@ public class DeclarationsChecker { REMOVE_IF_SUBTYPE_IN_THE_SET { @Override public boolean removeNeeded(JetType subject, JetType other) { - return JetTypeChecker.INSTANCE.isSubtypeOf(other, subject); + return JetTypeChecker.DEFAULT.isSubtypeOf(other, subject); } }, REMOVE_IF_SUPERTYPE_IN_THE_SET { @Override public boolean removeNeeded(JetType subject, JetType other) { - return JetTypeChecker.INSTANCE.isSubtypeOf(subject, other); + return JetTypeChecker.DEFAULT.isSubtypeOf(subject, other); } }; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegatedPropertyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegatedPropertyResolver.java index 3cc288d0deb..327a1c81b5d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegatedPropertyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegatedPropertyResolver.java @@ -98,7 +98,7 @@ public class DelegatedPropertyResolver { JetType propertyType = propertyDescriptor.getType(); /* Do not check return type of get() method of delegate for properties with DeferredType because property type is taken from it */ - if (!(propertyType instanceof DeferredType) && returnType != null && !JetTypeChecker.INSTANCE.isSubtypeOf(returnType, propertyType)) { + if (!(propertyType instanceof DeferredType) && returnType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(returnType, propertyType)) { Call call = trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, propertyDescriptor.getGetter()); assert call != null : "Call should exists for " + propertyDescriptor.getGetter(); trace.report(DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index c5f96ec1e87..9afc4b1a47a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -760,7 +760,7 @@ public class DescriptorResolver { boolean isClassObjectConstraint, BindingTrace trace ) { - if (!TypeUtils.canHaveSubtypes(JetTypeChecker.INSTANCE, upperBoundType)) { + if (!TypeUtils.canHaveSubtypes(JetTypeChecker.DEFAULT, upperBoundType)) { if (isClassObjectConstraint) { trace.report(FINAL_CLASS_OBJECT_UPPER_BOUND.on(upperBound, upperBoundType)); } @@ -1360,7 +1360,7 @@ public class DescriptorResolver { ) { for (JetType bound : typeParameterDescriptor.getUpperBounds()) { JetType substitutedBound = substitutor.safeSubstitute(bound, Variance.INVARIANT); - if (!JetTypeChecker.INSTANCE.isSubtypeOf(typeArgument, substitutedBound)) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(typeArgument, substitutedBound)) { trace.report(UPPER_BOUND_VIOLATED.on(jetTypeArgument, substitutedBound, typeArgument)); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadUtil.java index 6eccea98512..8bf3e2fc931 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadUtil.java @@ -71,7 +71,7 @@ public class OverloadUtil { JetType superValueParameterType = OverridingUtil.getUpperBound(superValueParameters.get(i)); JetType subValueParameterType = OverridingUtil.getUpperBound(subValueParameters.get(i)); // TODO: compare erasure - if (!JetTypeChecker.INSTANCE.equalTypes(superValueParameterType, subValueParameterType)) { + if (!JetTypeChecker.DEFAULT.equalTypes(superValueParameterType, subValueParameterType)) { return OverridingUtil.OverrideCompatibilityInfo .valueParameterTypeMismatch(superValueParameterType, subValueParameterType, INCOMPATIBLE); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index 2b091f3459f..e5b1be44da5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -733,7 +733,7 @@ public class OverrideResolver { JetType substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE); assert substitutedSuperReturnType != null; - return JetTypeChecker.INSTANCE.isSubtypeOf(subReturnType, substitutedSuperReturnType); + return JetTypeChecker.DEFAULT.isSubtypeOf(subReturnType, substitutedSuperReturnType); } @Nullable @@ -768,7 +768,7 @@ public class OverrideResolver { JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getType(), Variance.OUT_VARIANCE); assert substitutedSuperReturnType != null; - return JetTypeChecker.INSTANCE.equalTypes(subDescriptor.getType(), substitutedSuperReturnType); + return JetTypeChecker.DEFAULT.equalTypes(subDescriptor.getType(), substitutedSuperReturnType); } private void checkOverrideForComponentFunction(@NotNull final CallableMemberDescriptor componentFunction) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java index 91f2d1d64e8..3eba4a8a729 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java @@ -74,7 +74,7 @@ public class ArgumentTypeResolver { if (actualType == PLACEHOLDER_FUNCTION_TYPE) { return isFunctionOrErrorType(expectedType) || KotlinBuiltIns.getInstance().isAnyOrNullableAny(expectedType); //todo function type extends } - return JetTypeChecker.INSTANCE.isSubtypeOf(actualType, expectedType); + return JetTypeChecker.DEFAULT.isSubtypeOf(actualType, expectedType); } private static boolean isFunctionOrErrorType(@NotNull JetType supertype) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformer.java index 1718a96ab8d..40f3d802061 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformer.java @@ -102,18 +102,22 @@ public class CallTransformer { assert candidate.getDescriptor() instanceof VariableDescriptor; boolean hasReceiver = candidate.getReceiverArgument().exists(); - Call variableCall = stripCallArguments(task); + Call variableCall = stripCallArguments(task.call); + ResolutionCandidate variableCandidate = getVariableCallCandidate(candidate, variableCall); if (!hasReceiver) { CallCandidateResolutionContext context = CallCandidateResolutionContext.create( - ResolvedCallImpl.create(candidate, candidateTrace, task.tracing, task.dataFlowInfoForArguments), task, candidateTrace, task.tracing, variableCall); + ResolvedCallImpl.create(variableCandidate, candidateTrace, task.tracing, task.dataFlowInfoForArguments), task, candidateTrace, task.tracing, variableCall); return Collections.singleton(context); } CallCandidateResolutionContext contextWithReceiver = createContextWithChainedTrace( - candidate, variableCall, candidateTrace, task, ReceiverValue.NO_RECEIVER); + variableCandidate, variableCall, candidateTrace, task, ReceiverValue.NO_RECEIVER); Call variableCallWithoutReceiver = stripReceiver(variableCall); ResolutionCandidate candidateWithoutReceiver = ResolutionCandidate.create( - candidate.getCall(), candidate.getDescriptor(), candidate.getThisObject(), ReceiverValue.NO_RECEIVER, + variableCandidate.getCall(), + variableCandidate.getDescriptor(), + variableCandidate.getThisObject(), + ReceiverValue.NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, false); CallCandidateResolutionContext contextWithoutReceiver = createContextWithChainedTrace( @@ -131,8 +135,22 @@ public class CallTransformer { return CallCandidateResolutionContext.create(resolvedCall, task, chainedTrace, task.tracing, call, receiverValue); } - private Call stripCallArguments(@NotNull ResolutionTask task) { - return new DelegatingCall(task.call) { + @NotNull + private ResolutionCandidate getVariableCallCandidate( + @NotNull ResolutionCandidate candidate, + @NotNull Call variableCall + ) { + return ResolutionCandidate.create( + variableCall, + candidate.getDescriptor(), + candidate.getThisObject(), + candidate.getReceiverArgument(), + candidate.getExplicitReceiverKind(), + candidate.isSafeCall()); + } + + private Call stripCallArguments(@NotNull Call call) { + return new DelegatingCall(call) { @Override public JetValueArgumentList getValueArgumentList() { return null; @@ -160,6 +178,15 @@ public class CallTransformer { public JetTypeArgumentList getTypeArgumentList() { return null; } + + @NotNull + @Override + public JetElement getCallElement() { + JetExpression calleeExpression = getCalleeExpression(); + assert calleeExpression != null : "No callee expression: " + getCallElement().getText(); + + return calleeExpression; + } }; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index 1fb1f127305..2259350c967 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -735,7 +735,7 @@ public class CandidateResolver { Set possibleTypes = dataFlowInfoForArgument.getPossibleTypes(dataFlowValue); if (possibleTypes.isEmpty()) return type; - return TypeUtils.intersect(JetTypeChecker.INSTANCE, possibleTypes); + return TypeUtils.intersect(JetTypeChecker.DEFAULT, possibleTypes); } private ValueArgumentsCheckingResult checkAllValueArguments( @@ -859,7 +859,7 @@ public class CandidateResolver { List variants = AutoCastUtils.getAutoCastVariantsExcludingReceiver(context.trace.getBindingContext(), context.dataFlowInfo, receiverToCast); for (JetType possibleType : variants) { - if (JetTypeChecker.INSTANCE.isSubtypeOf(possibleType, expectedType)) { + if (JetTypeChecker.DEFAULT.isSubtypeOf(possibleType, expectedType)) { return possibleType; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java index 2e6bdc26d93..4991d3c4785 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java @@ -116,7 +116,7 @@ public class AutoCastUtils { } if (subTypes.isEmpty()) return null; - JetType intersection = TypeUtils.intersect(JetTypeChecker.INSTANCE, subTypes); + JetType intersection = TypeUtils.intersect(JetTypeChecker.DEFAULT, subTypes); if (intersection == null || !intersection.getConstructor().isDenotable()) { return receiverParameterType; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java index aec3e3562d3..ccaaaf8b12b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java @@ -94,7 +94,7 @@ public class ConstraintsUtil { JetType substitutedUpperBound = constraintSystem.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT); assert substitutedUpperBound != null : "We wanted to substitute projections as a result for " + typeParameter; - if (!JetTypeChecker.INSTANCE.isSubtypeOf(type, substitutedUpperBound)) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(type, substitutedUpperBound)) { return false; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java index 03901b7d70a..2bd6d32a3c8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java @@ -239,7 +239,7 @@ public class OverloadingConflictResolver { } private boolean typeMoreSpecific(@NotNull JetType specific, @NotNull JetType general) { - return JetTypeChecker.INSTANCE.isSubtypeOf(specific, general) || + return JetTypeChecker.DEFAULT.isSubtypeOf(specific, general) || numericTypeMoreSpecific(specific, general); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java index 39eb7ff3f84..5166f22bd2a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java @@ -25,7 +25,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetReferenceExpression; import org.jetbrains.jet.lang.psi.JetSuperExpression; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastUtils; @@ -326,7 +325,7 @@ public class TaskPrioritizer { if (expectedThisObject == null) return true; List receivers = scope.getImplicitReceiversHierarchy(); for (ReceiverParameterDescriptor receiver : receivers) { - if (JetTypeChecker.INSTANCE.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) { + if (JetTypeChecker.DEFAULT.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) { // TODO : Autocasts & nullability candidate.setThisObject(expectedThisObject.getValue()); return true; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantChecker.java index ade5431b98a..58b04689557 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantChecker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantChecker.java @@ -90,7 +90,7 @@ public class CompileTimeConstantChecker { if (!noExpectedTypeOrError(expectedType)) { JetType valueType = value.getType(KotlinBuiltIns.getInstance()); - if (!JetTypeChecker.INSTANCE.isSubtypeOf(valueType, expectedType)) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) { return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "integer", expectedType)); } } @@ -107,7 +107,7 @@ public class CompileTimeConstantChecker { } if (!noExpectedTypeOrError(expectedType)) { JetType valueType = value.getType(KotlinBuiltIns.getInstance()); - if (!JetTypeChecker.INSTANCE.isSubtypeOf(valueType, expectedType)) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) { return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "floating-point", expectedType)); } } @@ -119,7 +119,7 @@ public class CompileTimeConstantChecker { @NotNull JetConstantExpression expression ) { if (!noExpectedTypeOrError(expectedType) - && !JetTypeChecker.INSTANCE.isSubtypeOf(builtIns.getBooleanType(), expectedType)) { + && !JetTypeChecker.DEFAULT.isSubtypeOf(builtIns.getBooleanType(), expectedType)) { return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "boolean", expectedType)); } return false; @@ -127,7 +127,7 @@ public class CompileTimeConstantChecker { private boolean checkCharValue(CompileTimeConstant constant, JetType expectedType, JetConstantExpression expression) { if (!noExpectedTypeOrError(expectedType) - && !JetTypeChecker.INSTANCE.isSubtypeOf(builtIns.getCharType(), expectedType)) { + && !JetTypeChecker.DEFAULT.isSubtypeOf(builtIns.getCharType(), expectedType)) { return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "character", expectedType)); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java index 95e8f484b89..e9032ba4682 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java @@ -66,8 +66,8 @@ public class CastDiagnosticsUtil { for (JetType aType : aTypes) { for (JetType bType : bTypes) { - if (JetTypeChecker.INSTANCE.isSubtypeOf(aType, bType)) return true; - if (JetTypeChecker.INSTANCE.isSubtypeOf(bType, aType)) return true; + if (JetTypeChecker.DEFAULT.isSubtypeOf(aType, bType)) return true; + if (JetTypeChecker.DEFAULT.isSubtypeOf(bType, aType)) return true; } } @@ -100,7 +100,7 @@ public class CastDiagnosticsUtil { } private static boolean isFinal(@NotNull JetType type) { - return !TypeUtils.canHaveSubtypes(JetTypeChecker.INSTANCE, type); + return !TypeUtils.canHaveSubtypes(JetTypeChecker.DEFAULT, type); } private static boolean isTrait(@NotNull JetType type) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 9b836f765d3..edf331d8c97 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -212,7 +212,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { context.trace.report(CAST_NEVER_SUCCEEDS.on(expression.getOperationReference())); } else { - JetTypeChecker typeChecker = JetTypeChecker.INSTANCE; + JetTypeChecker typeChecker = JetTypeChecker.DEFAULT; // Upcast? if (typeChecker.isSubtypeOf(actualType, targetType)) { if (!typeChecker.isSubtypeOf(targetType, actualType)) { @@ -378,8 +378,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (labelName != null) { LabelResolver.LabeledReceiverResolutionResult resolutionResult = LabelResolver.INSTANCE.resolveThisOrSuperLabel(expression, context, Name.identifier(labelName)); - if (onlyClassReceivers && resolutionResult.success()) { - if (!isDeclaredInClass(resolutionResult.getReceiverParameterDescriptor())) { + if (resolutionResult.success()) { + ReceiverParameterDescriptor receiverParameterDescriptor = resolutionResult.getReceiverParameterDescriptor(); + recordThisOrSuperCallInTraceAndCallExtension(context, receiverParameterDescriptor, expression); + if (onlyClassReceivers && !isDeclaredInClass(receiverParameterDescriptor)) { return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(NO_RECEIVER_PARAMETER); } } @@ -402,7 +404,6 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (result != NO_RECEIVER_PARAMETER) { context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), result.getContainingDeclaration()); recordThisOrSuperCallInTraceAndCallExtension(context, result, expression); - } return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(result); } @@ -661,13 +662,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetType result; if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) { assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor(); - if (JetTypeChecker.INSTANCE.isSubtypeOf(returnType, KotlinBuiltIns.getInstance().getUnitType())) { + if (KotlinBuiltIns.getInstance().isUnit(returnType)) { result = ErrorUtils.createErrorType(KotlinBuiltIns.getInstance().getUnit().getName().asString()); context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign)); } else { JetType receiverType = receiver.getType(); - if (!JetTypeChecker.INSTANCE.isSubtypeOf(returnType, receiverType)) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(returnType, receiverType)) { context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType)); } else { @@ -882,7 +883,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:", right); traceInterpretingRightAsNullableAny.record(EXPRESSION_TYPE, right, KotlinBuiltIns.getInstance().getNullableAnyType()); - Call call = CallMaker.makeCallWithExpressions(operationSign, receiver, null, operationSign, Collections.singletonList(right)); + Call call = CallMaker.makeCallWithExpressions(expression, receiver, null, operationSign, Collections.singletonList(right)); ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny); OverloadResolutionResults resolutionResults = components.callResolver.resolveCallWithGivenName(newContext, call, operationSign, OperatorConventions.EQUALS); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java index 4bc6fd8baff..73331a549fb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java @@ -221,7 +221,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { if (typeReference != null) { type = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, true); if (expectedType != null) { - if (!JetTypeChecker.INSTANCE.isSubtypeOf(expectedType, type)) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(expectedType, type)) { context.trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(declaredParameter, expectedType)); } } @@ -278,7 +278,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { // This is needed for ControlStructureTypingVisitor#visitReturnExpression() to properly type-check returned expressions functionDescriptor.setReturnType(declaredReturnType); if (expectedReturnType != null) { - if (!JetTypeChecker.INSTANCE.isSubtypeOf(declaredReturnType, expectedReturnType)) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(declaredReturnType, expectedReturnType)) { context.trace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(returnTypeRef, expectedReturnType)); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index c8b74780ff3..e0ce8f2fcc5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -355,7 +355,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { variableDescriptor = components.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(context.scope, loopParameter, context.trace); JetType actualParameterType = variableDescriptor.getType(); if (expectedParameterType != null && - !JetTypeChecker.INSTANCE.isSubtypeOf(expectedParameterType, actualParameterType)) { + !JetTypeChecker.DEFAULT.isSubtypeOf(expectedParameterType, actualParameterType)) { context.trace.report(TYPE_MISMATCH_IN_FOR_LOOP.on(typeReference, expectedParameterType, actualParameterType)); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java index 270f4d1cba7..d8bf889087c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java @@ -164,7 +164,7 @@ public class DataFlowUtils { recordExpectedType(trace, expression, expectedType); if (expressionType == null || noExpectedType(expectedType) || !expectedType.getConstructor().isDenotable() || - JetTypeChecker.INSTANCE.isSubtypeOf(expressionType, expectedType)) { + JetTypeChecker.DEFAULT.isSubtypeOf(expressionType, expectedType)) { return expressionType; } @@ -179,7 +179,7 @@ public class DataFlowUtils { DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, expressionType, trace.getBindingContext()); for (JetType possibleType : dataFlowInfo.getPossibleTypes(dataFlowValue)) { - if (JetTypeChecker.INSTANCE.isSubtypeOf(possibleType, expectedType)) { + if (JetTypeChecker.DEFAULT.isSubtypeOf(possibleType, expectedType)) { AutoCastUtils.recordCastOrError(expression, possibleType, trace, dataFlowValue.isStableIdentifier(), false); return possibleType; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index 852453f93cb..c56aee232cf 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -96,7 +96,7 @@ public class ExpressionTypingUtils { } public static boolean isBoolean(@NotNull JetType type) { - return JetTypeChecker.INSTANCE.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType()); + return JetTypeChecker.DEFAULT.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType()); } public static boolean ensureBooleanResult(JetExpression operationSign, Name name, JetType resultType, ExpressionTypingContext context) { @@ -401,7 +401,7 @@ public class ExpressionTypingUtils { context.trace.record(COMPONENT_RESOLVED_CALL, entry, results.getResultingCall()); componentType = results.getResultingDescriptor().getReturnType(); if (componentType != null && !noExpectedType(expectedType) - && !JetTypeChecker.INSTANCE.isSubtypeOf(componentType, expectedType)) { + && !JetTypeChecker.DEFAULT.isSubtypeOf(componentType, expectedType)) { context.trace.report( COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.on(reportErrorsOn, componentName, componentType, expectedType)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java index 87d10554c36..28e9841d690 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java @@ -175,6 +175,9 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito scope, context.dataFlowInfo, context.trace, /* needCompleteAnalysis = */ true); ModifiersChecker.create(context.trace).checkModifiersForLocalDeclaration(function, functionDescriptor); + if (!function.hasBody()) { + context.trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor)); + } return DataFlowUtils.checkStatementType(function, context, context.dataFlowInfo); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java index 89dc437e390..f9b036c492a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java @@ -100,21 +100,14 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { DataFlowInfo elseDataFlowInfo = context.dataFlowInfo; for (JetWhenEntry whenEntry : expression.getEntries()) { DataFlowInfos infosForCondition = getDataFlowInfosForEntryCondition( - whenEntry, context, subjectExpression, subjectType, subjectDataFlowValue); - DataFlowInfo dataFlowInfoForEntryBody; - if (infosForCondition == null) { - dataFlowInfoForEntryBody = elseDataFlowInfo; - } - else { - dataFlowInfoForEntryBody = infosForCondition.thenInfo.and(elseDataFlowInfo); - elseDataFlowInfo = elseDataFlowInfo.and(infosForCondition.elseInfo); - } + whenEntry, context.replaceDataFlowInfo(elseDataFlowInfo), subjectExpression, subjectType, subjectDataFlowValue); + elseDataFlowInfo = elseDataFlowInfo.and(infosForCondition.elseInfo); JetExpression bodyExpression = whenEntry.getExpression(); if (bodyExpression != null) { WritableScope scopeToExtend = newWritableScopeImpl(context, "Scope extended in when entry"); ExpressionTypingContext newContext = contextWithExpectedType - .replaceScope(scopeToExtend).replaceDataFlowInfo(dataFlowInfoForEntryBody).replaceContextDependency(INDEPENDENT); + .replaceScope(scopeToExtend).replaceDataFlowInfo(infosForCondition.thenInfo).replaceContextDependency(INDEPENDENT); CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION; JetTypeInfo typeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope( scopeToExtend, Collections.singletonList(bodyExpression), coercionStrategy, newContext, context.trace); @@ -141,7 +134,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { return JetTypeInfo.create(null, commonDataFlowInfo); } - @Nullable + @NotNull private DataFlowInfos getDataFlowInfosForEntryCondition( @NotNull JetWhenEntry whenEntry, @NotNull ExpressionTypingContext context, @@ -149,13 +142,12 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { @NotNull JetType subjectType, @NotNull DataFlowValue subjectDataFlowValue ) { - JetWhenCondition[] conditions = whenEntry.getConditions(); if (whenEntry.isElse()) { - return null; + return new DataFlowInfos(context.dataFlowInfo); } DataFlowInfos infos = null; - for (JetWhenCondition condition : conditions) { + for (JetWhenCondition condition : whenEntry.getConditions()) { DataFlowInfos conditionInfos = checkWhenCondition(subjectExpression, subjectExpression == null, subjectType, condition, context, subjectDataFlowValue); if (infos != null) { @@ -165,7 +157,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { infos = conditionInfos; } } - return infos; + return infos != null ? infos : new DataFlowInfos(context.dataFlowInfo); } private DataFlowInfos checkWhenCondition( @@ -238,6 +230,10 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { this.thenInfo = thenInfo; this.elseInfo = elseInfo; } + + private DataFlowInfos(DataFlowInfo info) { + this(info, info); + } } private DataFlowInfos checkTypeForExpressionCondition( @@ -258,7 +254,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { context = context.replaceDataFlowInfo(typeInfo.getDataFlowInfo()); if (conditionExpected) { JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType(); - if (!JetTypeChecker.INSTANCE.equalTypes(booleanType, type)) { + if (!JetTypeChecker.DEFAULT.equalTypes(booleanType, type)) { context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(expression, type)); } else { @@ -298,7 +294,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { context.trace.report(Errors.USELESS_NULLABLE_CHECK.on(nullableType)); } checkTypeCompatibility(context, type, subjectType, typeReferenceAfterIs); - if (CastDiagnosticsUtil.isCastErased(subjectType, type, JetTypeChecker.INSTANCE)) { + if (CastDiagnosticsUtil.isCastErased(subjectType, type, JetTypeChecker.DEFAULT)) { context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(typeReferenceAfterIs, type)); } return new DataFlowInfos(context.dataFlowInfo.establishSubtyping(subjectDataFlowValue, type), context.dataFlowInfo); diff --git a/compiler/frontend/src/org/jetbrains/jet/plugin/MainFunctionDetector.java b/compiler/frontend/src/org/jetbrains/jet/plugin/MainFunctionDetector.java index 46b9dcfff8f..33fb189f141 100644 --- a/compiler/frontend/src/org/jetbrains/jet/plugin/MainFunctionDetector.java +++ b/compiler/frontend/src/org/jetbrains/jet/plugin/MainFunctionDetector.java @@ -80,7 +80,7 @@ public class MainFunctionDetector { List typeArguments = parameterType.getArguments(); if (typeArguments.size() == 1) { JetType typeArgument = typeArguments.get(0).getType(); - if (JetTypeChecker.INSTANCE.equalTypes(typeArgument, kotlinBuiltIns.getStringType())) { + if (JetTypeChecker.DEFAULT.equalTypes(typeArgument, kotlinBuiltIns.getStringType())) { return true; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/Slices.java b/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/Slices.java index bf3276e13e5..693e816088a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/Slices.java +++ b/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/Slices.java @@ -16,12 +16,14 @@ package org.jetbrains.jet.util.slicedmap; +import com.intellij.openapi.diagnostic.Logger; import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.List; public class Slices { + private static final Logger LOG = Logger.getInstance(Slices.class); public static final RewritePolicy ONLY_REWRITE_TO_EQUAL = new RewritePolicy() { @Override @@ -33,7 +35,7 @@ public class Slices { public boolean processRewrite(WritableSlice slice, K key, V oldValue, V newValue) { if (!((oldValue == null && newValue == null) || (oldValue != null && oldValue.equals(newValue)))) { // NOTE: Use BindingTraceContext.TRACK_REWRITES to debug this exception - throw new IllegalStateException("Rewrite at slice " + slice + + LOG.error("Rewrite at slice " + slice + " key: " + key + " old value: " + oldValue + '@' + System.identityHashCode(oldValue) + " new value: " + newValue + '@' + System.identityHashCode(newValue)); diff --git a/compiler/testData/asJava/lightClasses/delegation/Function.java b/compiler/testData/asJava/lightClasses/delegation/Function.java index 3f57046f3c5..8b07898697d 100644 --- a/compiler/testData/asJava/lightClasses/delegation/Function.java +++ b/compiler/testData/asJava/lightClasses/delegation/Function.java @@ -1,5 +1,4 @@ public final class Derived implements kotlin.jvm.internal.KObject, Base { - @org.jetbrains.annotations.NotNull public Derived(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "x") Base x) { /* compiled code */ } @org.jetbrains.annotations.NotNull diff --git a/compiler/testData/asJava/lightClasses/delegation/Property.java b/compiler/testData/asJava/lightClasses/delegation/Property.java index 7a570ffd6b7..b5d491bd57f 100644 --- a/compiler/testData/asJava/lightClasses/delegation/Property.java +++ b/compiler/testData/asJava/lightClasses/delegation/Property.java @@ -1,5 +1,4 @@ public final class Derived implements kotlin.jvm.internal.KObject, Base { - @org.jetbrains.annotations.NotNull public Derived(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "x") Base x) { /* compiled code */ } @org.jetbrains.annotations.NotNull diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Class.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Class.java index 02944a909ca..fd52f2a3e75 100644 --- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Class.java +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Class.java @@ -34,7 +34,6 @@ public final class Class implements kotlin.jvm.internal.KObject { @org.jetbrains.annotations.Nullable public final java.lang.String getNullableVar() { /* compiled code */ } - @org.jetbrains.annotations.NotNull public final void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "", type = "?") java.lang.String p) { /* compiled code */ } @org.jetbrains.annotations.NotNull @@ -43,7 +42,6 @@ public final class Class implements kotlin.jvm.internal.KObject { @org.jetbrains.annotations.NotNull public final java.lang.String getNotNullVar() { /* compiled code */ } - @org.jetbrains.annotations.NotNull public final void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "") java.lang.String p) { /* compiled code */ } @org.jetbrains.annotations.Nullable @@ -55,7 +53,6 @@ public final class Class implements kotlin.jvm.internal.KObject { public final java.lang.String getNotNullVarWithGetSet() { /* compiled code */ } @org.jetbrains.annotations.Nullable - @org.jetbrains.annotations.NotNull public final void setNotNullVarWithGetSet(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "v") java.lang.String v) { /* compiled code */ } @org.jetbrains.annotations.NotNull @@ -69,6 +66,5 @@ public final class Class implements kotlin.jvm.internal.KObject { @org.jetbrains.annotations.NotNull public final void setNullableVarWithGetSet(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "v", type = "?") java.lang.String v) { /* compiled code */ } - @org.jetbrains.annotations.NotNull public Class() { /* compiled code */ } } diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassObjectField.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassObjectField.java index 60f5378a83c..4de2e6cccee 100644 --- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassObjectField.java +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassObjectField.java @@ -4,7 +4,6 @@ public final class ClassObjectField implements kotlin.jvm.internal.KObject { private static final java.lang.String y = ""; public static final ClassObjectField.object object$; - @org.jetbrains.annotations.NotNull public ClassObjectField() { /* compiled code */ } public static final class object implements kotlin.jvm.internal.KObject { diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructor.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructor.java index f781f98d627..3daedf91e11 100644 --- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructor.java +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructor.java @@ -1,4 +1,3 @@ public final class ClassWithConstructor implements kotlin.jvm.internal.KObject { - @org.jetbrains.annotations.NotNull public ClassWithConstructor(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "nullable", type = "?") java.lang.String nullable, @org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "notNull") java.lang.String notNull) { /* compiled code */ } } diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructorAndProperties.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructorAndProperties.java index b59925f9a57..61917952f6e 100644 --- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructorAndProperties.java +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructorAndProperties.java @@ -10,6 +10,5 @@ public final class ClassWithConstructorAndProperties implements kotlin.jvm.inter @org.jetbrains.annotations.NotNull public final java.lang.String getNotNull() { /* compiled code */ } - @org.jetbrains.annotations.NotNull public ClassWithConstructorAndProperties(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "nullable", type = "?") java.lang.String nullable, @org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "notNull") java.lang.String notNull) { /* compiled code */ } } diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.java new file mode 100644 index 00000000000..4a518c5ca97 --- /dev/null +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.java @@ -0,0 +1,11 @@ +public final class C implements kotlin.jvm.internal.KObject, Tr { + private final int v = 1; + + @org.jetbrains.annotations.NotNull + public java.lang.Integer foo() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public java.lang.Integer getV() { /* compiled code */ } + + public C() { /* compiled code */ } +} \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.kt new file mode 100644 index 00000000000..274a682a4f6 --- /dev/null +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.kt @@ -0,0 +1,12 @@ +// C + +trait Tr { + fun foo(): Any + val v: Any +} + +class C: Tr { + override fun foo() = 1 + override val v = 1 +} + diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.java new file mode 100644 index 00000000000..c4eae18b754 --- /dev/null +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.java @@ -0,0 +1,4 @@ +public final class _DefaultPackage { + @org.jetbrains.annotations.Nullable + public static final kotlin.Unit foo() { /* compiled code */ } +} \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.kt new file mode 100644 index 00000000000..ac605d0a0ae --- /dev/null +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.kt @@ -0,0 +1,3 @@ +// _DefaultPackage + +fun foo(): Unit? = null \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.java new file mode 100644 index 00000000000..ea46f1f8b4d --- /dev/null +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.java @@ -0,0 +1,5 @@ +public final class C implements kotlin.jvm.internal.KObject, Base { + public void foo() { /* compiled code */ } + + public C() { /* compiled code */ } +} \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.kt new file mode 100644 index 00000000000..1efb58ec710 --- /dev/null +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.kt @@ -0,0 +1,9 @@ +// C + +trait Base { + fun foo(): Any +} + +class C : Base { + override fun foo(): Unit {} +} \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Synthetic.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Synthetic.java index 4bbf5fb52b9..c9e411d88d4 100644 --- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Synthetic.java +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Synthetic.java @@ -1,14 +1,11 @@ public final class Synthetic implements kotlin.jvm.internal.KObject { private final void foo() { /* compiled code */ } - @org.jetbrains.annotations.NotNull public Synthetic() { /* compiled code */ } public final class Inner implements kotlin.jvm.internal.KObject { - @org.jetbrains.annotations.NotNull public final void test() { /* compiled code */ } - @org.jetbrains.annotations.NotNull public Inner() { /* compiled code */ } } } diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Trait.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Trait.java index ebe1ccec524..466a27bd758 100644 --- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Trait.java +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Trait.java @@ -25,7 +25,6 @@ public interface Trait extends kotlin.jvm.internal.KObject { @org.jetbrains.annotations.Nullable java.lang.String getNullableVar(); - @org.jetbrains.annotations.NotNull void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "", type = "?") java.lang.String p); @org.jetbrains.annotations.NotNull @@ -34,6 +33,5 @@ public interface Trait extends kotlin.jvm.internal.KObject { @org.jetbrains.annotations.NotNull java.lang.String getNotNullVar(); - @org.jetbrains.annotations.NotNull void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "") java.lang.String p); } diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.java new file mode 100644 index 00000000000..51f7748cedb --- /dev/null +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.java @@ -0,0 +1,5 @@ +public final class C implements kotlin.jvm.internal.KObject, Base { + public void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "t") kotlin.Unit t) { /* compiled code */ } + + public C() { /* compiled code */ } +} \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.kt new file mode 100644 index 00000000000..be4e460f616 --- /dev/null +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.kt @@ -0,0 +1,9 @@ +// C + +trait Base { + fun foo(t: T): T +} + +class C : Base { + override fun foo(t: Unit) {} +} \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.java new file mode 100644 index 00000000000..f1fe4fc2028 --- /dev/null +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.java @@ -0,0 +1,3 @@ +public final class _DefaultPackage { + public static final void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "s") kotlin.Unit s) { /* compiled code */ } +} \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.kt new file mode 100644 index 00000000000..b417517b964 --- /dev/null +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.kt @@ -0,0 +1,3 @@ +// _DefaultPackage + +fun foo(s: Unit) {} \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.java new file mode 100644 index 00000000000..b2e287c1e78 --- /dev/null +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.java @@ -0,0 +1,3 @@ +public final class _DefaultPackage { + public static final void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "s") java.lang.String s) { /* compiled code */ } +} \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.kt new file mode 100644 index 00000000000..4d2cdda1da3 --- /dev/null +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.kt @@ -0,0 +1,3 @@ +// _DefaultPackage + +fun foo(s: String) {} \ No newline at end of file diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/_DefaultPackage.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/_DefaultPackage.java index 49af58748db..7c58f38e1fa 100644 --- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/_DefaultPackage.java +++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/_DefaultPackage.java @@ -9,7 +9,6 @@ public final class _DefaultPackage { @org.jetbrains.annotations.NotNull public static final java.lang.String getNotNullVar() { /* compiled code */ } - @org.jetbrains.annotations.NotNull public static final void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "") java.lang.String p) { /* compiled code */ } @org.jetbrains.annotations.Nullable @@ -17,7 +16,6 @@ public final class _DefaultPackage { public static final java.lang.String getNotNullVarWithGetSet() { /* compiled code */ } @org.jetbrains.annotations.Nullable - @org.jetbrains.annotations.NotNull public static final void setNotNullVarWithGetSet(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "v") java.lang.String v) { /* compiled code */ } @org.jetbrains.annotations.Nullable @@ -30,7 +28,6 @@ public final class _DefaultPackage { @org.jetbrains.annotations.Nullable public static final java.lang.String getNullableVar() { /* compiled code */ } - @org.jetbrains.annotations.NotNull public static final void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "", type = "?") java.lang.String p) { /* compiled code */ } @org.jetbrains.annotations.NotNull diff --git a/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions b/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions index 2afa0f4bfc8..bc3499991b5 100644 --- a/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions +++ b/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions @@ -14,14 +14,14 @@ L0: 2 mark({ val b: Boolean if (1 < 2) { use(b) } else { b = true } }) v(val b: Boolean) INIT: in: {} out: {b=D} mark(if (1 < 2) { use(b) } else { b = true }) INIT: in: {b=D} out: {b=D} - mark(1 < 2) r(1) -> r(2) -> + mark(1 < 2) call(<, compareTo|, ) -> jf(L2|) - 3 mark({ use(b) }) - mark(use(b)) USE: in: {b=READ} out: {b=READ} + 3 mark({ use(b) }) USE: in: {b=READ} out: {b=READ} r(b) -> USE: in: {} out: {b=READ} + mark(use(b)) call(use, use|) -> 2 jmp(L3) USE: in: {} out: {} L2: diff --git a/compiler/testData/cfg-variables/basic/IfWithUninitialized.values b/compiler/testData/cfg-variables/basic/IfWithUninitialized.values index 886eac6e86c..9e8d37ccb96 100644 --- a/compiler/testData/cfg-variables/basic/IfWithUninitialized.values +++ b/compiler/testData/cfg-variables/basic/IfWithUninitialized.values @@ -9,18 +9,18 @@ fun foo() { } } --------------------- -1 NEW() -2 NEW() -1 < 2 NEW(, ) -b NEW() -use(b) NEW() -{ use(b) } COPY -true NEW() -if (1 < 2) { use(b) } else { b = true } COPY -{ val b: Boolean if (1 < 2) { use(b) } else { b = true } } COPY +1 : {<: Comparable} NEW() +2 : Int NEW() +1 < 2 : Boolean NEW(, ) +b : {<: Any?} NEW() +use(b) : * NEW() +{ use(b) } : * COPY +true : Boolean NEW() +if (1 < 2) { use(b) } else { b = true } : * COPY +{ val b: Boolean if (1 < 2) { use(b) } else { b = true } } : * COPY ===================== == use == fun use(vararg a: Any?) = a --------------------- -a NEW() +a : {<: Array} NEW() ===================== diff --git a/compiler/testData/cfg-variables/basic/InitializedNotDeclared.values b/compiler/testData/cfg-variables/basic/InitializedNotDeclared.values index 13de2c9986d..6b99c7aaf59 100644 --- a/compiler/testData/cfg-variables/basic/InitializedNotDeclared.values +++ b/compiler/testData/cfg-variables/basic/InitializedNotDeclared.values @@ -6,5 +6,5 @@ class A { val x: Int } --------------------- -1 NEW() +1 : Int NEW() ===================== diff --git a/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.instructions b/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.instructions index da8b9a71781..c1df1eb55e0 100644 --- a/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.instructions +++ b/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.instructions @@ -39,14 +39,14 @@ L3: magic(x: Int) -> INIT: in: {x=D} out: {x=D} w(x|) INIT: in: {x=D} out: {x=ID} 4 mark(val y = x + a use(a)) INIT: in: {x=ID} out: {x=ID} - v(val y = x + a) INIT: in: {x=ID} out: {x=ID, y=D} - mark(x + a) INIT: in: {x=ID, y=D} out: {x=ID, y=D} USE: in: {a=READ, x=READ} out: {a=READ, x=READ} - r(x) -> USE: in: {a=READ} out: {a=READ, x=READ} + v(val y = x + a) INIT: in: {x=ID} out: {x=ID, y=D} USE: in: {a=READ, x=READ} out: {a=READ, x=READ} + r(x) -> INIT: in: {x=ID, y=D} out: {x=ID, y=D} USE: in: {a=READ} out: {a=READ, x=READ} r(a) -> + mark(x + a) call(+, plus|, ) -> - w(y|) INIT: in: {x=ID, y=D} out: {x=ID, y=ID} - mark(use(a)) INIT: in: {x=ID, y=ID} out: {x=ID, y=ID} USE: in: {a=READ} out: {a=READ} - r(a) -> USE: in: {} out: {a=READ} + w(y|) INIT: in: {x=ID, y=D} out: {x=ID, y=ID} USE: in: {a=READ} out: {a=READ} + r(a) -> INIT: in: {x=ID, y=ID} out: {x=ID, y=ID} USE: in: {} out: {a=READ} + mark(use(a)) call(use, use|) -> L4: 3 INIT: in: {x=ID} out: {x=ID} diff --git a/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.values b/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.values index c7195b6fb36..4c2009adf92 100644 --- a/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.values +++ b/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.values @@ -7,8 +7,8 @@ fun foo() { } } --------------------- -1 NEW() -{ (x: Int) -> val y = x + a use(a) } NEW() +1 : Int NEW() +{ (x: Int) -> val y = x + a use(a) } : {<: (Int) -> Array} NEW() ===================== == anonymous_0 == { (x: Int) -> @@ -16,15 +16,15 @@ fun foo() { use(a) } --------------------- -x NEW() -a NEW() -x + a NEW(, ) -a NEW() -use(a) NEW() -val y = x + a use(a) COPY +x : Int NEW() +a : Int NEW() +x + a : Int NEW(, ) +a : {<: Any?} NEW() +use(a) : {<: Array} NEW() +val y = x + a use(a) : {<: Array} COPY ===================== == use == fun use(vararg a: Any?) = a --------------------- -a NEW() +a : {<: Array} NEW() ===================== diff --git a/compiler/testData/cfg-variables/basic/VariablesInitialization.values b/compiler/testData/cfg-variables/basic/VariablesInitialization.values index 4288c843063..99f30cf9766 100644 --- a/compiler/testData/cfg-variables/basic/VariablesInitialization.values +++ b/compiler/testData/cfg-variables/basic/VariablesInitialization.values @@ -6,10 +6,10 @@ fun foo() { 42 } --------------------- -1 NEW() -2 NEW() -42 NEW() -{ val a = 1 val b: Int b = 2 42 } COPY +1 : Int NEW() +2 : Int NEW() +42 : * NEW() +{ val a = 1 val b: Int b = 2 42 } : * COPY ===================== == bar == fun bar(foo: Foo) { @@ -18,13 +18,13 @@ fun bar(foo: Foo) { 42 } --------------------- -foo NEW() -c NEW() -foo.c COPY -foo NEW() -2 NEW() -42 NEW() -{ foo.c foo.c = 2 42 } COPY +foo : {<: Foo} NEW() +c : * NEW() +foo.c : * COPY +foo : {<: Foo} NEW() +2 : Int NEW() +42 : * NEW() +{ foo.c foo.c = 2 42 } : * COPY ===================== == Foo == trait Foo { diff --git a/compiler/testData/cfg-variables/basic/VariablesUsage.instructions b/compiler/testData/cfg-variables/basic/VariablesUsage.instructions index c4b90e6cd19..e7ef96d159d 100644 --- a/compiler/testData/cfg-variables/basic/VariablesUsage.instructions +++ b/compiler/testData/cfg-variables/basic/VariablesUsage.instructions @@ -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) -> INIT: in: {a=D} out: {a=D} - w(a|) 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) -> USE: in: {a=WRITTEN_AFTER_READ} out: {a=READ} + w(a|) INIT: in: {a=D} out: {a=ID} USE: in: {a=READ} out: {a=READ} + r(a) -> INIT: in: {a=ID} out: {a=ID} USE: in: {a=WRITTEN_AFTER_READ} out: {a=READ} + mark(use(a)) call(use, use|) -> r(2) -> USE: in: {a=WRITTEN_AFTER_READ} out: {a=WRITTEN_AFTER_READ} w(a|) USE: in: {a=READ} out: {a=WRITTEN_AFTER_READ} - mark(use(a)) USE: in: {a=READ} out: {a=READ} r(a) -> USE: in: {} out: {a=READ} + mark(use(a)) call(use, use|) -> L1: 1 INIT: in: {} out: {} diff --git a/compiler/testData/cfg-variables/basic/VariablesUsage.values b/compiler/testData/cfg-variables/basic/VariablesUsage.values index f9713ca80ce..99496514298 100644 --- a/compiler/testData/cfg-variables/basic/VariablesUsage.values +++ b/compiler/testData/cfg-variables/basic/VariablesUsage.values @@ -6,13 +6,13 @@ fun foo() { use(a) } --------------------- -1 NEW() -a NEW() -use(a) NEW() -2 NEW() -a NEW() -use(a) NEW() -{ var a = 1 use(a) a = 2 use(a) } COPY +1 : Int NEW() +a : Int NEW() +use(a) : * NEW() +2 : Int NEW() +a : Int NEW() +use(a) : * NEW() +{ var a = 1 use(a) a = 2 use(a) } : * COPY ===================== == bar == fun bar() { @@ -20,10 +20,10 @@ fun bar() { b = 3 } --------------------- -3 NEW() +3 : Int NEW() ===================== == use == fun use(a: Int) = a --------------------- -a NEW() +a : Int NEW() ===================== diff --git a/compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.instructions b/compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.instructions index fe4512be268..ff2efa51a56 100644 --- a/compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.instructions +++ b/compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.instructions @@ -32,16 +32,16 @@ L3: magic(x: Int) -> INIT: in: {x=D} out: {x=D} w(x|) 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) -> USE: in: {sum=READ, x=READ} out: {sum=READ, x=READ} r(sum|) -> USE: in: {x=READ} out: {sum=READ, x=READ} - mark(x - 1) r(x) -> r(1) -> + mark(x - 1) call(-, minus|, ) -> + mark(sum(x - 1)) call(sum, invoke|, ) -> USE: in: {x=READ} out: {x=READ} r(x) -> USE: in: {} out: {x=READ} + mark(sum(x - 1) + x) call(+, plus|, ) -> L4: 2 @@ -127,10 +127,10 @@ class TestOther { L0: 1 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) -> USE: in: {x=READ} out: {x=READ} + magic(x) -> INIT: in: {x=D} out: {x=D} USE: in: {x=READ} out: {x=READ} r(x|) -> USE: in: {} out: {x=READ} r(1) -> + mark(x + 1) call(+, plus|, ) -> w(x|) INIT: in: {x=D} out: {x=ID} L1: diff --git a/compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.values b/compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.values index 0dfc529f7e4..2c25e090ff8 100644 --- a/compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.values +++ b/compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.values @@ -5,21 +5,21 @@ class TestFunctionLiteral { } } --------------------- -{ (x: Int) -> sum(x - 1) + x } NEW() +{ (x: Int) -> sum(x - 1) + x } : {<: (Int) -> Int} NEW() ===================== == anonymous_0 == { (x: Int) -> sum(x - 1) + x } --------------------- -sum NEW() -x NEW() -1 NEW() -x - 1 NEW(, ) -sum(x - 1) NEW(, ) -x NEW() -sum(x - 1) + x NEW(, ) -sum(x - 1) + x COPY +sum : {<: (Int) -> Int} NEW() +x : Int NEW() +1 : Int NEW() +x - 1 : Int NEW(, ) +sum(x - 1) : Int NEW(, ) +x : Int NEW() +sum(x - 1) + x : Int NEW(, ) +sum(x - 1) + x : Int COPY ===================== == A == open class A(val a: A) @@ -37,23 +37,23 @@ class TestObjectLiteral { } } --------------------- -obj NEW() -obj NEW() -object: A(obj) { { val x = obj } fun foo() { val y = obj } } NEW() +obj : * NEW() +obj : {<: A} NEW() +object: A(obj) { { val x = obj } fun foo() { val y = obj } } : {<: A} NEW() ===================== == foo == fun foo() { val y = obj } --------------------- -obj NEW() +obj : {<: A} NEW() ===================== == TestOther == class TestOther { val x: Int = x + 1 } --------------------- -x NEW() -1 NEW() -x + 1 NEW(, ) +x : Int NEW() +1 : Int NEW() +x + 1 : Int NEW(, ) ===================== diff --git a/compiler/testData/cfg-variables/bugs/varInitializationInIf.instructions b/compiler/testData/cfg-variables/bugs/varInitializationInIf.instructions index 96d9c9a1284..c21437571e3 100644 --- a/compiler/testData/cfg-variables/bugs/varInitializationInIf.instructions +++ b/compiler/testData/cfg-variables/bugs/varInitializationInIf.instructions @@ -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) -> r(2) -> + mark(1 < 2) call(<, compareTo|, ) -> jf(L2|) 3 mark({ b = false }) @@ -29,10 +29,10 @@ L2: r(true) -> USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ} w(b|) 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) -> USE: in: {} out: {b=READ} error(use, No resolved call) + mark(use(b)) magic(use(b)|) -> L1: 1 INIT: in: {} out: {} diff --git a/compiler/testData/cfg-variables/bugs/varInitializationInIf.values b/compiler/testData/cfg-variables/bugs/varInitializationInIf.values index d87c23dbb1c..e14fe8f08f1 100644 --- a/compiler/testData/cfg-variables/bugs/varInitializationInIf.values +++ b/compiler/testData/cfg-variables/bugs/varInitializationInIf.values @@ -10,12 +10,12 @@ fun foo() { use(b) } --------------------- -1 NEW() -2 NEW() -1 < 2 NEW(, ) -false NEW() -true NEW() -b NEW() -use(b) NEW() -{ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) } COPY +1 : {<: Comparable} NEW() +2 : Int NEW() +1 < 2 : Boolean NEW(, ) +false : Boolean NEW() +true : Boolean NEW() +b : * NEW() +use(b) : * NEW() +{ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) } : * COPY ===================== diff --git a/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.instructions b/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.instructions index aaa804160de..6c56fdbdd94 100644 --- a/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.instructions +++ b/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.instructions @@ -18,22 +18,22 @@ L0: v(numbers: Collection) INIT: in: {} out: {numbers=D} magic(numbers: Collection) -> INIT: in: {numbers=D} out: {numbers=D} w(numbers|) INIT: in: {numbers=D} out: {numbers=ID} - 2 mark({ for (i in numbers) { val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue } }) INIT: in: {numbers=ID} out: {numbers=ID} - 3 mark(for (i in numbers) { val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue }) USE: in: {numbers=READ} out: {numbers=READ} - r(numbers) -> USE: in: {} out: {numbers=READ} + 2 mark({ for (i in numbers) { val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue } }) INIT: in: {numbers=ID} out: {numbers=ID} USE: in: {numbers=READ} out: {numbers=READ} + 3 r(numbers) -> USE: in: {} out: {numbers=READ} v(i) INIT: in: {numbers=ID} out: {i=D, numbers=ID} L3: jmp?(L2) INIT: in: {i=D, numbers=ID} out: {i=D, numbers=ID} L4 [loop entry point]: L5 [body entry point]: magic(numbers|) -> - w(i|) INIT: in: {i=D, numbers=ID} out: {i=ID, numbers=ID} USE: in: {} out: {} - 4 mark({ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue }) INIT: in: {i=ID, numbers=ID} out: {i=ID, numbers=ID} + w(i|) INIT: in: {i=D, numbers=ID} out: {i=ID, numbers=ID} + mark(for (i in numbers) { val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue }) INIT: in: {i=ID, numbers=ID} out: {i=ID, numbers=ID} USE: in: {} out: {} + 4 mark({ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue }) v(val b: Boolean) INIT: in: {i=ID, numbers=ID} out: {b=D, i=ID, numbers=ID} mark(if (1 < 2) { b = false } else { b = true }) INIT: in: {b=D, i=ID, numbers=ID} out: {b=D, i=ID, numbers=ID} - mark(1 < 2) r(1) -> r(2) -> + mark(1 < 2) call(<, compareTo|, ) -> jf(L6|) 5 mark({ b = false }) @@ -45,8 +45,8 @@ L6: r(true) -> USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ} w(b|) INIT: in: {b=D, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ} L7: - 4 mark(use(b)) INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {b=READ} out: {b=READ} - r(b) -> USE: in: {} out: {b=READ} + 4 r(b) -> INIT: in: {b=ID, i=ID, numbers=ID} out: {b=ID, i=ID, numbers=ID} USE: in: {} out: {b=READ} + mark(use(b)) call(use, use|) -> jmp(L4 [loop entry point]) USE: in: {} out: {} - 3 jmp?(L4 [loop entry point]) diff --git a/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.values b/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.values index 5719f3b7cfe..4b4eee75d7b 100644 --- a/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.values +++ b/compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.values @@ -13,17 +13,17 @@ fun foo(numbers: Collection) { } } --------------------- -numbers NEW() -1 NEW() -2 NEW() -1 < 2 NEW(, ) -false NEW() -true NEW() -b NEW() -use(b) NEW() +numbers : {<: Iterable} NEW() +1 : {<: Comparable} NEW() +2 : Int NEW() +1 < 2 : Boolean NEW(, ) +false : Boolean NEW() +true : Boolean NEW() +b : {<: Any?} NEW() +use(b) : * NEW() ===================== == use == fun use(vararg a: Any?) = a --------------------- -a NEW() +a : {<: Array} NEW() ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.instructions index 7708be03b46..4825042e39c 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.instructions @@ -20,9 +20,9 @@ L4 [body entry point]: r(2) -> w(a|) L5 [condition entry point]: - mark(a > 0) r(a) -> r(0) -> + mark(a > 0) call(>, compareTo|, ) -> jt(L2 [loop entry point]|) USE: in: {a=READ} out: {a=READ} L3 [loop exit point]: diff --git a/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.values b/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.values index 6168d89842d..b54a25d7dbe 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/doWhileScope.values @@ -7,11 +7,11 @@ fun foo() { "after" } --------------------- -"before" NEW() -2 NEW() -a NEW() -0 NEW() -a > 0 NEW(, ) -"after" NEW() -{ "before" do { var a = 2 } while (a > 0) "after" } COPY +"before" : * NEW() +2 : Int NEW() +a : {<: Comparable} NEW() +0 : Int NEW() +a > 0 : Boolean NEW(, ) +"after" : * NEW() +{ "before" do { var a = 2 } while (a > 0) "after" } : * COPY ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/forScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/forScope.instructions index c9152b6723d..a061ddc9d89 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/forScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/forScope.instructions @@ -12,10 +12,9 @@ L0: 2 mark({ "before" for (i in 1..10) { val a = i } "after" }) mark("before") r("before") -> USE: in: {} out: {} - 3 mark(for (i in 1..10) { val a = i }) - mark(1..10) - r(1) -> + 3 r(1) -> r(10) -> + mark(1..10) call(.., rangeTo|, ) -> v(i) INIT: in: {} out: {i=D} L3: @@ -24,7 +23,8 @@ L4 [loop entry point]: L5 [body entry point]: magic(1..10|) -> w(i|) INIT: in: {i=D} out: {i=ID} - 4 mark({ val a = i }) INIT: in: {i=ID} out: {i=ID} + mark(for (i in 1..10) { val a = i }) INIT: in: {i=ID} out: {i=ID} + 4 mark({ val a = i }) v(val a = i) INIT: in: {i=ID} out: {a=D, i=ID} r(i) -> INIT: in: {a=D, i=ID} out: {a=D, i=ID} w(a|) INIT: in: {a=D, i=ID} out: {a=ID, i=ID} diff --git a/compiler/testData/cfg-variables/lexicalScopes/forScope.values b/compiler/testData/cfg-variables/lexicalScopes/forScope.values index a48bf428fda..8bcf01b3d9b 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/forScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/forScope.values @@ -7,11 +7,11 @@ fun foo() { "after" } --------------------- -"before" NEW() -1 NEW() -10 NEW() -1..10 NEW(, ) -i NEW() -"after" NEW() -{ "before" for (i in 1..10) { val a = i } "after" } COPY +"before" : * NEW() +1 : Int NEW() +10 : Int NEW() +1..10 : {<: Iterable} NEW(, ) +i : Int NEW() +"after" : * NEW() +{ "before" for (i in 1..10) { val a = i } "after" } : * COPY ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.instructions index a9f72bf6857..ad9463aaccc 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.instructions @@ -43,10 +43,10 @@ L3: magic(x: Int) -> INIT: in: {x=D} out: {x=D} w(x|) INIT: in: {x=D} out: {x=ID} 4 mark(val a = x + b) INIT: in: {x=ID} out: {x=ID} - v(val a = x + b) INIT: in: {x=ID} out: {a=D, x=ID} - mark(x + b) INIT: in: {a=D, x=ID} out: {a=D, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ} - r(x) -> USE: in: {b=READ} out: {b=READ, x=READ} + v(val a = x + b) INIT: in: {x=ID} out: {a=D, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ} + r(x) -> INIT: in: {a=D, x=ID} out: {a=D, x=ID} USE: in: {b=READ} out: {b=READ, x=READ} r(b) -> USE: in: {} out: {b=READ} + mark(x + b) call(+, plus|, ) -> w(a|) INIT: in: {a=D, x=ID} out: {a=ID, x=ID} L4: diff --git a/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.values b/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.values index 5f8baa9bc50..94790e1fd76 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.values @@ -8,18 +8,18 @@ fun foo() { "after" } --------------------- -"before" NEW() -1 NEW() -{ (x: Int) -> val a = x + b } NEW() -"after" NEW() -{ "before" val b = 1 val f = { (x: Int) -> val a = x + b } "after" } COPY +"before" : * NEW() +1 : Int NEW() +{ (x: Int) -> val a = x + b } : {<: (Int) -> Unit} NEW() +"after" : * NEW() +{ "before" val b = 1 val f = { (x: Int) -> val a = x + b } "after" } : * COPY ===================== == anonymous_0 == { (x: Int) -> val a = x + b } --------------------- -x NEW() -b NEW() -x + b NEW(, ) +x : Int NEW() +b : Int NEW() +x + b : Int NEW(, ) ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/ifScope.values b/compiler/testData/cfg-variables/lexicalScopes/ifScope.values index 83e8b451ad0..2b5ab5da777 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/ifScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/ifScope.values @@ -10,10 +10,10 @@ fun foo() { "after" } --------------------- -"before" NEW() -true NEW() -1 NEW() -2 NEW() -"after" NEW() -{ "before" if (true) { val a = 1 } else { val b = 2 } "after" } COPY +"before" : * NEW() +true : Boolean NEW() +1 : Int NEW() +2 : Int NEW() +"after" : * NEW() +{ "before" if (true) { val a = 1 } else { val b = 2 } "after" } : * COPY ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/localClass.values b/compiler/testData/cfg-variables/lexicalScopes/localClass.values index c9e1ecde4a3..6787b010d9d 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/localClass.values +++ b/compiler/testData/cfg-variables/lexicalScopes/localClass.values @@ -12,15 +12,15 @@ fun foo() { "after" } --------------------- -"before" NEW() -x NEW() -"after" NEW() -{ "before" class A(val x: Int) { { val a = x } fun foo() { val b = x } } "after" } COPY +"before" : * NEW() +x : Int NEW() +"after" : * NEW() +{ "before" class A(val x: Int) { { val a = x } fun foo() { val b = x } } "after" } : * COPY ===================== == foo == fun foo() { val b = x } --------------------- -x NEW() +x : Int NEW() ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.instructions index fec9e2c51c1..e92d11ab224 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.instructions @@ -39,10 +39,10 @@ L3: magic(x: Int) -> INIT: in: {x=D} out: {x=D} w(x|) INIT: in: {x=D} out: {x=ID} 4 mark({ val a = x + b }) INIT: in: {x=ID} out: {x=ID} - v(val a = x + b) INIT: in: {x=ID} out: {a=D, x=ID} - mark(x + b) INIT: in: {a=D, x=ID} out: {a=D, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ} - r(x) -> USE: in: {b=READ} out: {b=READ, x=READ} + v(val a = x + b) INIT: in: {x=ID} out: {a=D, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ} + r(x) -> INIT: in: {a=D, x=ID} out: {a=D, x=ID} USE: in: {b=READ} out: {b=READ, x=READ} r(b) -> USE: in: {} out: {b=READ} + mark(x + b) call(+, plus|, ) -> w(a|) INIT: in: {a=D, x=ID} out: {a=ID, x=ID} L4: diff --git a/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.values b/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.values index d995e457ecb..0cd7d1c50ea 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.values @@ -8,17 +8,17 @@ fun foo() { "after" } --------------------- -"before" NEW() -1 NEW() -"after" NEW() -{ "before" val b = 1 fun local(x: Int) { val a = x + b } "after" } COPY +"before" : * NEW() +1 : Int NEW() +"after" : * NEW() +{ "before" val b = 1 fun local(x: Int) { val a = x + b } "after" } : * COPY ===================== == local == fun local(x: Int) { val a = x + b } --------------------- -x NEW() -b NEW() -x + b NEW(, ) +x : Int NEW() +b : Int NEW() +x + b : Int NEW(, ) ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/localFunctionScopeWithoutBody.instructions b/compiler/testData/cfg-variables/lexicalScopes/localFunctionScopeWithoutBody.instructions index 38ee650f5a1..6053403f52c 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/localFunctionScopeWithoutBody.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/localFunctionScopeWithoutBody.instructions @@ -33,10 +33,10 @@ L3: 3 INIT: in: {} out: {} v(x: Int) INIT: in: {} out: {x=D} magic(x: Int) -> INIT: in: {x=D} out: {x=D} - w(x|) INIT: in: {x=D} out: {x=ID} - mark(x + b) INIT: in: {x=ID} out: {x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ} - r(x) -> USE: in: {b=READ} out: {b=READ, x=READ} + w(x|) INIT: in: {x=D} out: {x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ} + r(x) -> INIT: in: {x=ID} out: {x=ID} USE: in: {b=READ} out: {b=READ, x=READ} r(b) -> USE: in: {} out: {b=READ} + mark(x + b) call(+, plus|, ) -> L4: diff --git a/compiler/testData/cfg-variables/lexicalScopes/localFunctionScopeWithoutBody.values b/compiler/testData/cfg-variables/lexicalScopes/localFunctionScopeWithoutBody.values index 75d4a6fd6dc..b70862c6513 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/localFunctionScopeWithoutBody.values +++ b/compiler/testData/cfg-variables/lexicalScopes/localFunctionScopeWithoutBody.values @@ -6,15 +6,15 @@ fun foo() { "after" } --------------------- -"before" NEW() -1 NEW() -"after" NEW() -{ "before" val b = 1 fun local(x: Int) = x + b "after" } COPY +"before" : * NEW() +1 : Int NEW() +"after" : * NEW() +{ "before" val b = 1 fun local(x: Int) = x + b "after" } : * COPY ===================== == local == fun local(x: Int) = x + b --------------------- -x NEW() -b NEW() -x + b NEW(, ) +x : Int NEW() +b : Int NEW() +x + b : Int NEW(, ) ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/localObject.values b/compiler/testData/cfg-variables/lexicalScopes/localObject.values index ac41b36e842..0c9ae1d8ecf 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/localObject.values +++ b/compiler/testData/cfg-variables/lexicalScopes/localObject.values @@ -12,15 +12,15 @@ fun foo() { "after" } --------------------- -"before" NEW() -1 NEW() -"after" NEW() -{ "before" object A { { val a = 1 } fun foo() { val b = 2 } } "after" } COPY +"before" : * NEW() +1 : Int NEW() +"after" : * NEW() +{ "before" object A { { val a = 1 } fun foo() { val b = 2 } } "after" } : * COPY ===================== == foo == fun foo() { val b = 2 } --------------------- -2 NEW() +2 : Int NEW() ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.values b/compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.values index 73e6fa3cdef..0fc6f4bc18c 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.values @@ -12,16 +12,16 @@ fun foo() { "after" } --------------------- -"before" NEW() -1 NEW() -object { { val x = 1 } fun foo() { val a = 2 } } NEW() -"after" NEW() -{ "before" val bar = object { { val x = 1 } fun foo() { val a = 2 } } "after" } COPY +"before" : * NEW() +1 : Int NEW() +object { { val x = 1 } fun foo() { val a = 2 } } : NEW() +"after" : * NEW() +{ "before" val bar = object { { val x = 1 } fun foo() { val a = 2 } } "after" } : * COPY ===================== == foo == fun foo() { val a = 2 } --------------------- -2 NEW() +2 : Int NEW() ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/propertyAccessorScope.values b/compiler/testData/cfg-variables/lexicalScopes/propertyAccessorScope.values index ba1ceaa3737..a38dc2dc87b 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/propertyAccessorScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/propertyAccessorScope.values @@ -17,12 +17,12 @@ get() { return $a } --------------------- -$a NEW() +$a : Int NEW() ===================== == set_a == set(v: Int) { $a = v } --------------------- -v NEW() +v : Int NEW() ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/tryScope.values b/compiler/testData/cfg-variables/lexicalScopes/tryScope.values index 03919986b84..ce7d64a84c6 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/tryScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/tryScope.values @@ -13,12 +13,12 @@ fun foo() { "after" } --------------------- -"before" NEW() -foo() NEW() -{ foo() } COPY -e NEW() -1 NEW() -try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 } COPY -"after" NEW() -{ "before" try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 } "after" } COPY +"before" : * NEW() +foo() : * NEW() +{ foo() } : * COPY +e : {<: Exception} NEW() +1 : Int NEW() +try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 } : * COPY +"after" : * NEW() +{ "before" try { foo() } catch (e: Exception) { val a = e } finally { val a = 1 } "after" } : * COPY ===================== diff --git a/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions b/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions index 50d2a76ed4b..2dec72a8ad3 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions +++ b/compiler/testData/cfg-variables/lexicalScopes/whileScope.instructions @@ -12,10 +12,10 @@ L0: 2 mark({ "before" while (true) { val a: Int } "after" }) mark("before") r("before") -> - mark(while (true) { val a: Int }) L2 [loop entry point]: L5 [condition entry point]: r(true) -> + mark(while (true) { val a: Int }) L4 [body entry point]: 3 mark({ val a: Int }) v(val a: Int) INIT: in: {} out: {a=D} diff --git a/compiler/testData/cfg-variables/lexicalScopes/whileScope.values b/compiler/testData/cfg-variables/lexicalScopes/whileScope.values index 01858675810..a8c0d80a31a 100644 --- a/compiler/testData/cfg-variables/lexicalScopes/whileScope.values +++ b/compiler/testData/cfg-variables/lexicalScopes/whileScope.values @@ -7,8 +7,8 @@ fun foo() { "after" } --------------------- -"before" NEW() -true NEW() -"after" NEW() -{ "before" while (true) { val a: Int } "after" } COPY +"before" : * NEW() +true : * NEW() +"after" : * NEW() +{ "before" while (true) { val a: Int } "after" } : * COPY ===================== diff --git a/compiler/testData/cfg/arrays/ArrayAccess.instructions b/compiler/testData/cfg/arrays/ArrayAccess.instructions index 67a47d4ca48..0e7994e6ff5 100644 --- a/compiler/testData/cfg/arrays/ArrayAccess.instructions +++ b/compiler/testData/cfg/arrays/ArrayAccess.instructions @@ -26,14 +26,16 @@ L0: mark(a[10]) r(a) -> r(10) -> + mark(a[10]) call(a[10], get|, ) -> r(100) -> - mark(a[10] += 1) mark(a[10]) r(a) -> r(10) -> + mark(a[10]) call(a[10], get|, ) -> r(1) -> + mark(a[10] += 1) call(+=, plus|, ) -> r(a) -> r(10) -> diff --git a/compiler/testData/cfg/arrays/ArrayAccess.values b/compiler/testData/cfg/arrays/ArrayAccess.values index bc136e3fe81..c6a7315e367 100644 --- a/compiler/testData/cfg/arrays/ArrayAccess.values +++ b/compiler/testData/cfg/arrays/ArrayAccess.values @@ -9,21 +9,21 @@ fun foo() { a[10] += 1 } --------------------- -Array NEW() -3 NEW() -a NEW() -10 NEW() -4 NEW() -a[10] = 4 NEW(, , ) -2 NEW() -a NEW() -10 NEW() -a[10] NEW(, ) -100 NEW() -a NEW() -10 NEW() -a[10] NEW(, ) -1 NEW() -a[10] += 1 NEW(, , ) -{ val a = Array 3 a[10] = 4 2 a[10] 100 a[10] += 1 } COPY +Array : {<: Array} NEW() +3 : * NEW() +a : {<: Array} NEW() +10 : Int NEW() +4 : Int NEW() +a[10] = 4 : * NEW(, , ) +2 : * NEW() +a : {<: Array} NEW() +10 : Int NEW() +a[10] : * NEW(, ) +100 : * NEW() +a : {<: Array} NEW() +10 : Int NEW() +a[10] : Int NEW(, ) +1 : Int NEW() +a[10] += 1 : * NEW(, , ) +{ val a = Array 3 a[10] = 4 2 a[10] 100 a[10] += 1 } : * COPY ===================== diff --git a/compiler/testData/cfg/arrays/ArrayOfFunctions.instructions b/compiler/testData/cfg/arrays/ArrayOfFunctions.instructions index 4b5c97d2f60..94932e91ba4 100644 --- a/compiler/testData/cfg/arrays/ArrayOfFunctions.instructions +++ b/compiler/testData/cfg/arrays/ArrayOfFunctions.instructions @@ -9,12 +9,13 @@ L0: magic(array: Array<(Int)->Unit>) -> w(array|) 2 mark({ array[11](3) }) - mark(array[11](3)) mark(array[11]) r(array) -> r(11) -> + mark(array[11]) call(array[11], get|, ) -> r(3) -> + mark(array[11](3)) call(array[11], invoke|, ) -> L1: 1 NEXT:[] diff --git a/compiler/testData/cfg/arrays/ArrayOfFunctions.values b/compiler/testData/cfg/arrays/ArrayOfFunctions.values index 789e1185393..2fd1a0238ac 100644 --- a/compiler/testData/cfg/arrays/ArrayOfFunctions.values +++ b/compiler/testData/cfg/arrays/ArrayOfFunctions.values @@ -3,10 +3,10 @@ fun test(array: Array<(Int)->Unit>) { array[11](3) } --------------------- -array NEW() -11 NEW() -array[11] NEW(, ) -3 NEW() -array[11](3) NEW(, ) -{ array[11](3) } COPY +array : {<: Array<(Int) -> Unit>} NEW() +11 : Int NEW() +array[11] : {<: (Int) -> Unit} NEW(, ) +3 : Int NEW() +array[11](3) : * NEW(, ) +{ array[11](3) } : * COPY ===================== diff --git a/compiler/testData/cfg/arrays/arrayAccessExpression.instructions b/compiler/testData/cfg/arrays/arrayAccessExpression.instructions index 6ac16f85361..31b610d5143 100644 --- a/compiler/testData/cfg/arrays/arrayAccessExpression.instructions +++ b/compiler/testData/cfg/arrays/arrayAccessExpression.instructions @@ -37,10 +37,11 @@ L0: 2 mark({ ab.getArray()[1] }) mark(ab.getArray()[1]) mark(ab.getArray()) - mark(getArray()) r(ab) -> + mark(getArray()) call(getArray, getArray|) -> r(1) -> + mark(ab.getArray()[1]) call(ab.getArray()[1], get|, ) -> L1: 1 NEXT:[] diff --git a/compiler/testData/cfg/arrays/arrayAccessExpression.values b/compiler/testData/cfg/arrays/arrayAccessExpression.values index fee89dd84b8..0328f66872c 100644 --- a/compiler/testData/cfg/arrays/arrayAccessExpression.values +++ b/compiler/testData/cfg/arrays/arrayAccessExpression.values @@ -13,10 +13,10 @@ fun test(ab: Ab) { ab.getArray()[1] } --------------------- -ab NEW() -getArray() NEW() -ab.getArray() COPY -1 NEW() -ab.getArray()[1] NEW(, ) -{ ab.getArray()[1] } COPY +ab : {<: Ab} NEW() +getArray() : {<: Array} NEW() +ab.getArray() : {<: Array} COPY +1 : Int NEW() +ab.getArray()[1] : * NEW(, ) +{ ab.getArray()[1] } : * COPY ===================== diff --git a/compiler/testData/cfg/arrays/arrayInc.instructions b/compiler/testData/cfg/arrays/arrayInc.instructions index 05096066b52..5916a920d52 100644 --- a/compiler/testData/cfg/arrays/arrayInc.instructions +++ b/compiler/testData/cfg/arrays/arrayInc.instructions @@ -9,11 +9,12 @@ L0: magic(a: Array) -> w(a|) 2 mark({ a[0]++ }) - mark(a[0]++) mark(a[0]) r(a) -> r(0) -> + mark(a[0]) call(a[0], get|, ) -> + mark(a[0]++) call(++, inc|) -> r(a) -> r(0) -> diff --git a/compiler/testData/cfg/arrays/arrayInc.values b/compiler/testData/cfg/arrays/arrayInc.values index 6f116496e1d..c2a550bd58b 100644 --- a/compiler/testData/cfg/arrays/arrayInc.values +++ b/compiler/testData/cfg/arrays/arrayInc.values @@ -3,9 +3,9 @@ fun foo(a: Array) { a[0]++ } --------------------- -a NEW() -0 NEW() -a[0] NEW(, ) -a[0]++ NEW(, , ) -{ a[0]++ } COPY +a : {<: Array} NEW() +0 : Int NEW() +a[0] : Int NEW(, ) +a[0]++ : Int COPY +{ a[0]++ } : Int COPY ===================== diff --git a/compiler/testData/cfg/arrays/arraySet.values b/compiler/testData/cfg/arrays/arraySet.values index bfed5c9d479..15ca1d7a79f 100644 --- a/compiler/testData/cfg/arrays/arraySet.values +++ b/compiler/testData/cfg/arrays/arraySet.values @@ -3,9 +3,9 @@ fun foo(a: Array) { a[1] = 2 } --------------------- -a NEW() -1 NEW() -2 NEW() -a[1] = 2 NEW(, , ) -{ a[1] = 2 } COPY +a : {<: Array} NEW() +1 : Int NEW() +2 : Int NEW() +a[1] = 2 : * NEW(, , ) +{ a[1] = 2 } : * COPY ===================== diff --git a/compiler/testData/cfg/arrays/arraySetPlusAssign.instructions b/compiler/testData/cfg/arrays/arraySetPlusAssign.instructions index e5629e1ca6a..4c01b6ae3ed 100644 --- a/compiler/testData/cfg/arrays/arraySetPlusAssign.instructions +++ b/compiler/testData/cfg/arrays/arraySetPlusAssign.instructions @@ -9,12 +9,13 @@ L0: magic(a: Array) -> w(a|) 2 mark({ a[0] += 1 }) - mark(a[0] += 1) mark(a[0]) r(a) -> r(0) -> + mark(a[0]) call(a[0], get|, ) -> r(1) -> + mark(a[0] += 1) call(+=, plus|, ) -> r(a) -> r(0) -> diff --git a/compiler/testData/cfg/arrays/arraySetPlusAssign.values b/compiler/testData/cfg/arrays/arraySetPlusAssign.values index bd6d86ed9b6..e25b40da814 100644 --- a/compiler/testData/cfg/arrays/arraySetPlusAssign.values +++ b/compiler/testData/cfg/arrays/arraySetPlusAssign.values @@ -3,10 +3,10 @@ fun foo(a: Array) { a[0] += 1 } --------------------- -a NEW() -0 NEW() -a[0] NEW(, ) -1 NEW() -a[0] += 1 NEW(, , ) -{ a[0] += 1 } COPY +a : {<: Array} NEW() +0 : Int NEW() +a[0] : Int NEW(, ) +1 : Int NEW() +a[0] += 1 : * NEW(, , ) +{ a[0] += 1 } : * COPY ===================== diff --git a/compiler/testData/cfg/basic/Basic.instructions b/compiler/testData/cfg/basic/Basic.instructions index 1283ba8fa66..6962e4a033a 100644 --- a/compiler/testData/cfg/basic/Basic.instructions +++ b/compiler/testData/cfg/basic/Basic.instructions @@ -26,34 +26,34 @@ L0: r(1) -> r(a) -> mark(2.toLong()) - mark(toLong()) r(2) -> + mark(toLong()) call(toLong, toLong|) -> - mark(foo(a, 3)) r(a) -> r(3) -> + mark(foo(a, 3)) call(foo, foo|, ) -> mark(genfun()) call(genfun, genfun) -> - mark(flfun {1}) mark({1}) jmp?(L2) NEXT:[r({1}) -> , d({1})] d({1}) NEXT:[] L2: r({1}) -> PREV:[jmp?(L2)] + mark(flfun {1}) call(flfun, flfun|) -> mark(3.equals(4)) - mark(equals(4)) r(3) -> r(4) -> + mark(equals(4)) call(equals, equals|, ) -> - mark(3 equals 4) r(3) -> r(4) -> + mark(3 equals 4) call(equals, equals|, ) -> - mark(1 + 2) r(1) -> r(2) -> + mark(1 + 2) call(+, plus|, ) -> r(a) -> jf(L5|) NEXT:[magic(a && true|, ) -> , r(true) -> ] diff --git a/compiler/testData/cfg/basic/Basic.values b/compiler/testData/cfg/basic/Basic.values index 979de60120b..2b597aef89a 100644 --- a/compiler/testData/cfg/basic/Basic.values +++ b/compiler/testData/cfg/basic/Basic.values @@ -17,40 +17,40 @@ fun f(a : Boolean) : Unit { } --------------------- -1 NEW() -a NEW() -2 NEW() -toLong() NEW() -2.toLong() COPY -a NEW() -3 NEW() -foo(a, 3) NEW(, ) -genfun() NEW() -{1} NEW() -flfun {1} NEW() -3 NEW() -4 NEW() -equals(4) NEW(, ) -3.equals(4) COPY -3 NEW() -4 NEW() -3 equals 4 NEW(, ) -1 NEW() -2 NEW() -1 + 2 NEW(, ) -a NEW() -true NEW() -a && true NEW(, ) -a NEW() -false NEW() -a || false NEW(, ) -{ 1 a 2.toLong() foo(a, 3) genfun() flfun {1} 3.equals(4) 3 equals 4 1 + 2 a && true a || false } COPY +1 : * NEW() +a : * NEW() +2 : {<: Number} NEW() +toLong() : * NEW() +2.toLong() : * COPY +a : Boolean NEW() +3 : Int NEW() +foo(a, 3) : * NEW(, ) +genfun() : * NEW() +{1} : {<: () -> Any} NEW() +flfun {1} : * NEW() +3 : OR{{<: Any}, {<: Any}} NEW() +4 : {<: Any?} NEW() +equals(4) : * NEW(, ) +3.equals(4) : * COPY +3 : OR{{<: Any}, {<: Any}} NEW() +4 : {<: Any?} NEW() +3 equals 4 : * NEW(, ) +1 : Int NEW() +2 : Int NEW() +1 + 2 : * NEW(, ) +a : Boolean NEW() +true : Boolean NEW() +a && true : * NEW(, ) +a : Boolean NEW() +false : Boolean NEW() +a || false : * NEW(, ) +{ 1 a 2.toLong() foo(a, 3) genfun() flfun {1} 3.equals(4) 3 equals 4 1 + 2 a && true a || false } : * COPY ===================== == anonymous_0 == {1} --------------------- -1 NEW() -1 COPY +1 : Int NEW() +1 : Int COPY ===================== == foo == fun foo(a : Boolean, b : Int) : Unit {} diff --git a/compiler/testData/cfg/basic/ShortFunction.values b/compiler/testData/cfg/basic/ShortFunction.values index c30b60d47d4..f2c7d17510e 100644 --- a/compiler/testData/cfg/basic/ShortFunction.values +++ b/compiler/testData/cfg/basic/ShortFunction.values @@ -1,5 +1,5 @@ == short == fun short() = 1 --------------------- -1 NEW() +1 : Int NEW() ===================== diff --git a/compiler/testData/cfg/bugs/jumpToOuterScope.instructions b/compiler/testData/cfg/bugs/jumpToOuterScope.instructions index b8644228f64..018c604f721 100644 --- a/compiler/testData/cfg/bugs/jumpToOuterScope.instructions +++ b/compiler/testData/cfg/bugs/jumpToOuterScope.instructions @@ -13,8 +13,7 @@ L0: magic(c: Collection) -> w(c|) 2 mark({ for (e in c) { { break } } }) - 3 mark(for (e in c) { { break } }) - r(c) -> + 3 r(c) -> v(e) L3: jmp?(L2) NEXT:[read (Unit), magic(c|) -> ] @@ -22,6 +21,7 @@ L4 [loop entry point]: L5 [body entry point]: magic(c|) -> PREV:[jmp?(L2), jmp?(L4 [loop entry point])] w(e|) + mark(for (e in c) { { break } }) 4 mark({ { break } }) mark({ break }) jmp?(L6) NEXT:[r({ break }) -> , d({ break })] diff --git a/compiler/testData/cfg/bugs/jumpToOuterScope.values b/compiler/testData/cfg/bugs/jumpToOuterScope.values index 3f158c01d81..f58075297ea 100644 --- a/compiler/testData/cfg/bugs/jumpToOuterScope.values +++ b/compiler/testData/cfg/bugs/jumpToOuterScope.values @@ -7,9 +7,9 @@ fun foo(c: Collection) { } } --------------------- -c NEW() -{ break } NEW() -{ { break } } COPY +c : {<: Iterable} NEW() +{ break } : * NEW() +{ { break } } : * COPY ===================== == anonymous_0 == { diff --git a/compiler/testData/cfg/controlStructures/Finally.instructions b/compiler/testData/cfg/controlStructures/Finally.instructions index 05e80d05c0e..07f32055e00 100644 --- a/compiler/testData/cfg/controlStructures/Finally.instructions +++ b/compiler/testData/cfg/controlStructures/Finally.instructions @@ -51,9 +51,9 @@ L0: 3 mark({ 1 if (2 > 3) { return } }) r(1) -> mark(if (2 > 3) { return }) - mark(2 > 3) r(2) -> r(3) -> + mark(2 > 3) call(>, compareTo|, ) -> jf(L3|) NEXT:[read (Unit), mark({ return })] 4 mark({ return }) @@ -136,9 +136,9 @@ L4: 4 5 mark(if (2 > 3) { return@l }) mark(if (2 > 3) { return@l }) - mark(2 > 3) r(2) -> r(3) -> + mark(2 > 3) call(>, compareTo|, ) -> jf(L6|) NEXT:[read (Unit), mark({ return@l })] 6 mark({ return@l }) @@ -204,9 +204,9 @@ L3: 5 mark({ 1 if (2 > 3) { return@l } }) r(1) -> mark(if (2 > 3) { return@l }) - mark(2 > 3) r(2) -> r(3) -> + mark(2 > 3) call(>, compareTo|, ) -> jf(L6|) NEXT:[read (Unit), mark({ return@l })] 6 mark({ return@l }) @@ -252,10 +252,10 @@ L0: 1 2 mark({ @l while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } } }) mark(@l while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } }) - mark(while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } }) L2 [loop entry point]: L5 [condition entry point]: - r(true) -> PREV:[mark(while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } }), jmp(L2 [loop entry point])] + r(true) -> PREV:[mark(@l while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } }), jmp(L2 [loop entry point])] + mark(while(true) { try { 1 if (2 > 3) { break @l } } finally { 2 } }) L4 [body entry point]: 3 mark({ try { 1 if (2 > 3) { break @l } } finally { 2 } }) mark(try { 1 if (2 > 3) { break @l } } finally { 2 }) @@ -263,9 +263,9 @@ L4 [body entry point]: 4 mark({ 1 if (2 > 3) { break @l } }) r(1) -> mark(if (2 > 3) { break @l }) - mark(2 > 3) r(2) -> r(3) -> + mark(2 > 3) call(>, compareTo|, ) -> jf(L7|) NEXT:[read (Unit), mark({ break @l })] 5 mark({ break @l }) @@ -318,17 +318,17 @@ L0: jmp?(L2 [onExceptionToFinallyBlock]) NEXT:[mark({ 2 }), mark({ @l while(true) { 1 if (2 > 3) { break @l } } 5 })] 3 mark({ @l while(true) { 1 if (2 > 3) { break @l } } 5 }) mark(@l while(true) { 1 if (2 > 3) { break @l } }) - mark(while(true) { 1 if (2 > 3) { break @l } }) L3 [loop entry point]: L6 [condition entry point]: - r(true) -> PREV:[mark(while(true) { 1 if (2 > 3) { break @l } }), jmp(L3 [loop entry point])] + r(true) -> PREV:[mark(@l while(true) { 1 if (2 > 3) { break @l } }), jmp(L3 [loop entry point])] + mark(while(true) { 1 if (2 > 3) { break @l } }) L5 [body entry point]: 4 mark({ 1 if (2 > 3) { break @l } }) r(1) -> mark(if (2 > 3) { break @l }) - mark(2 > 3) r(2) -> r(3) -> + mark(2 > 3) call(>, compareTo|, ) -> jf(L7|) NEXT:[read (Unit), mark({ break @l })] 5 mark({ break @l }) @@ -379,17 +379,17 @@ L0: jmp?(L2 [onExceptionToFinallyBlock]) NEXT:[mark({ 2 }), mark({ @l while(true) { 1 if (2 > 3) { break @l } } })] 3 mark({ @l while(true) { 1 if (2 > 3) { break @l } } }) mark(@l while(true) { 1 if (2 > 3) { break @l } }) - mark(while(true) { 1 if (2 > 3) { break @l } }) L3 [loop entry point]: L6 [condition entry point]: - r(true) -> PREV:[mark(while(true) { 1 if (2 > 3) { break @l } }), jmp(L3 [loop entry point])] + r(true) -> PREV:[mark(@l while(true) { 1 if (2 > 3) { break @l } }), jmp(L3 [loop entry point])] + mark(while(true) { 1 if (2 > 3) { break @l } }) L5 [body entry point]: 4 mark({ 1 if (2 > 3) { break @l } }) r(1) -> mark(if (2 > 3) { break @l }) - mark(2 > 3) r(2) -> r(3) -> + mark(2 > 3) call(>, compareTo|, ) -> jf(L7|) NEXT:[read (Unit), mark({ break @l })] 5 mark({ break @l }) @@ -439,10 +439,9 @@ L0: w(a|) 2 mark({ @l for (i in 1..a) { try { 1 if (2 > 3) { continue @l } } finally { 2 } } }) mark(@l for (i in 1..a) { try { 1 if (2 > 3) { continue @l } } finally { 2 } }) - 3 mark(for (i in 1..a) { try { 1 if (2 > 3) { continue @l } } finally { 2 } }) - mark(1..a) - r(1) -> + 3 r(1) -> r(a) -> + mark(1..a) call(.., rangeTo|, ) -> v(i) L3: @@ -451,15 +450,16 @@ L4 [loop entry point]: L5 [body entry point]: magic(1..a|) -> PREV:[jmp?(L2), jmp(L4 [loop entry point]), jmp?(L4 [loop entry point])] w(i|) + mark(for (i in 1..a) { try { 1 if (2 > 3) { continue @l } } finally { 2 } }) 4 mark({ try { 1 if (2 > 3) { continue @l } } finally { 2 } }) mark(try { 1 if (2 > 3) { continue @l } } finally { 2 }) jmp?(L6 [onExceptionToFinallyBlock]) NEXT:[mark({ 2 }), mark({ 1 if (2 > 3) { continue @l } })] 5 mark({ 1 if (2 > 3) { continue @l } }) r(1) -> mark(if (2 > 3) { continue @l }) - mark(2 > 3) r(2) -> r(3) -> + mark(2 > 3) call(>, compareTo|, ) -> jf(L7|) NEXT:[read (Unit), mark({ continue @l })] 6 mark({ continue @l }) @@ -515,10 +515,9 @@ L0: jmp?(L2 [onExceptionToFinallyBlock]) NEXT:[mark({ 2 }), mark({ @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 })] 3 mark({ @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 }) mark(@l for (i in 1..a) { 1 if (2 > 3) { continue @l } }) - 4 mark(for (i in 1..a) { 1 if (2 > 3) { continue @l } }) - mark(1..a) - r(1) -> + 4 r(1) -> r(a) -> + mark(1..a) call(.., rangeTo|, ) -> v(i) L4: @@ -527,12 +526,13 @@ L5 [loop entry point]: L6 [body entry point]: magic(1..a|) -> PREV:[jmp?(L3), jmp(L5 [loop entry point]), jmp?(L5 [loop entry point])] w(i|) + mark(for (i in 1..a) { 1 if (2 > 3) { continue @l } }) 5 mark({ 1 if (2 > 3) { continue @l } }) r(1) -> mark(if (2 > 3) { continue @l }) - mark(2 > 3) r(2) -> r(3) -> + mark(2 > 3) call(>, compareTo|, ) -> jf(L7|) NEXT:[read (Unit), mark({ continue @l })] 6 mark({ continue @l }) @@ -586,10 +586,9 @@ L0: jmp?(L2 [onExceptionToFinallyBlock]) NEXT:[mark({ 2 }), mark({ @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } })] 3 mark({ @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } }) mark(@l for (i in 1..a) { 1 if (2 > 3) { continue @l } }) - 4 mark(for (i in 1..a) { 1 if (2 > 3) { continue @l } }) - mark(1..a) - r(1) -> + 4 r(1) -> r(a) -> + mark(1..a) call(.., rangeTo|, ) -> v(i) L4: @@ -598,12 +597,13 @@ L5 [loop entry point]: L6 [body entry point]: magic(1..a|) -> PREV:[jmp?(L3), jmp(L5 [loop entry point]), jmp?(L5 [loop entry point])] w(i|) + mark(for (i in 1..a) { 1 if (2 > 3) { continue @l } }) 5 mark({ 1 if (2 > 3) { continue @l } }) r(1) -> mark(if (2 > 3) { continue @l }) - mark(2 > 3) r(2) -> r(3) -> + mark(2 > 3) call(>, compareTo|, ) -> jf(L7|) NEXT:[read (Unit), mark({ continue @l })] 6 mark({ continue @l }) @@ -691,22 +691,22 @@ L0: r(1) -> L3 [start finally]: 4 mark({ doSmth(3) }) - mark(doSmth(3)) r(3) -> + mark(doSmth(3)) call(doSmth, doSmth|) -> L4 [finish finally]: 3 ret(*|) L1 NEXT:[] - 2 jmp(L5 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] PREV:[] L2 [onExceptionToFinallyBlock]: 4 mark({ doSmth(3) }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] - mark(doSmth(3)) r(3) -> + mark(doSmth(3)) call(doSmth, doSmth|) -> 2 jmp(error) NEXT:[] L5 [skipFinallyToErrorBlock]: - 4 mark({ doSmth(3) }) PREV:[] -- mark(doSmth(3)) PREV:[] - r(3) -> PREV:[] +- mark(doSmth(3)) PREV:[] - call(doSmth, doSmth|) -> PREV:[] L1: 1 NEXT:[] PREV:[ret(*|) L1] @@ -738,8 +738,8 @@ L0: r(1) -> L4 [start finally]: 4 mark({ doSmth(3) }) - mark(doSmth(3)) r(3) -> + mark(doSmth(3)) call(doSmth, doSmth|) -> L5 [finish finally]: 3 ret(*|) L1 NEXT:[] @@ -749,22 +749,22 @@ L2 [onException]: magic(e: UnsupportedOperationException) -> w(e|) 4 mark({ doSmth(2) }) - mark(doSmth(2)) r(2) -> + mark(doSmth(2)) call(doSmth, doSmth|) -> 3 jmp(L6 [afterCatches]) L6 [afterCatches]: 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] L3 [onExceptionToFinallyBlock]: 4 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] - mark(doSmth(3)) r(3) -> + mark(doSmth(3)) call(doSmth, doSmth|) -> 2 jmp(error) NEXT:[] L7 [skipFinallyToErrorBlock]: 4 mark({ doSmth(3) }) PREV:[jmp(L7 [skipFinallyToErrorBlock])] - mark(doSmth(3)) r(3) -> + mark(doSmth(3)) call(doSmth, doSmth|) -> L1: 1 NEXT:[] PREV:[ret(*|) L1, call(doSmth, doSmth|) -> ] @@ -797,8 +797,8 @@ L2 [onException]: magic(e: UnsupportedOperationException) -> w(e|) 4 mark({ doSmth(2) }) - mark(doSmth(2)) r(2) -> + mark(doSmth(2)) call(doSmth, doSmth|) -> 3 jmp(L3 [afterCatches]) L1: @@ -832,8 +832,8 @@ L0: r(1) -> L4 [start finally]: 4 mark({ doSmth(3) }) - mark(doSmth(3)) r(3) -> + mark(doSmth(3)) call(doSmth, doSmth|) -> L5 [finish finally]: 3 ret(*|) L1 NEXT:[] @@ -845,8 +845,8 @@ L2 [onException]: 4 mark({ return 2 }) r(2) -> mark({ doSmth(3) }) - mark(doSmth(3)) r(3) -> + mark(doSmth(3)) call(doSmth, doSmth|) -> ret(*|) L1 NEXT:[] - 3 jmp(L6 [afterCatches]) PREV:[] @@ -854,14 +854,14 @@ L6 [afterCatches]: - 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] PREV:[] L3 [onExceptionToFinallyBlock]: 4 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] - mark(doSmth(3)) r(3) -> + mark(doSmth(3)) call(doSmth, doSmth|) -> 2 jmp(error) NEXT:[] L7 [skipFinallyToErrorBlock]: - 4 mark({ doSmth(3) }) PREV:[] -- mark(doSmth(3)) PREV:[] - r(3) -> PREV:[] +- mark(doSmth(3)) PREV:[] - call(doSmth, doSmth|) -> PREV:[] L1: 1 NEXT:[] PREV:[ret(*|) L1, ret(*|) L1] @@ -890,8 +890,8 @@ L0: jmp?(L2 [onException]) NEXT:[v(e: UnsupportedOperationException), jmp?(L3 [onExceptionToFinallyBlock])] jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ doSmth(3) }), mark({ doSmth(1) })] 3 mark({ doSmth(1) }) - mark(doSmth(1)) r(1) -> + mark(doSmth(1)) call(doSmth, doSmth|) -> 2 jmp(L4 [afterCatches]) NEXT:[jmp(L7 [skipFinallyToErrorBlock])] L2 [onException]: @@ -902,8 +902,8 @@ L2 [onException]: r(2) -> L5 [start finally]: 5 mark({ doSmth(3) }) - mark(doSmth(3)) r(3) -> + mark(doSmth(3)) call(doSmth, doSmth|) -> L6 [finish finally]: 4 ret(*|) L1 NEXT:[] @@ -912,14 +912,14 @@ L4 [afterCatches]: 2 jmp(L7 [skipFinallyToErrorBlock]) NEXT:[mark({ doSmth(3) })] PREV:[jmp(L4 [afterCatches])] L3 [onExceptionToFinallyBlock]: 5 mark({ doSmth(3) }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] - mark(doSmth(3)) r(3) -> + mark(doSmth(3)) call(doSmth, doSmth|) -> 2 jmp(error) NEXT:[] L7 [skipFinallyToErrorBlock]: 5 mark({ doSmth(3) }) PREV:[jmp(L7 [skipFinallyToErrorBlock])] - mark(doSmth(3)) r(3) -> + mark(doSmth(3)) call(doSmth, doSmth|) -> L1: 1 NEXT:[] PREV:[ret(*|) L1, call(doSmth, doSmth|) -> ] diff --git a/compiler/testData/cfg/controlStructures/Finally.values b/compiler/testData/cfg/controlStructures/Finally.values index d6ffe48bae5..8765ede1b36 100644 --- a/compiler/testData/cfg/controlStructures/Finally.values +++ b/compiler/testData/cfg/controlStructures/Finally.values @@ -7,12 +7,12 @@ fun t1() { } } --------------------- -1 NEW() -{ 1 } COPY -2 NEW() -{ 2 } COPY -try { 1 } finally { 2 } COPY -{ try { 1 } finally { 2 } } COPY +1 : * NEW() +{ 1 } : * COPY +2 : * NEW() +{ 2 } : * COPY +try { 1 } finally { 2 } : * COPY +{ try { 1 } finally { 2 } } : * COPY ===================== == t2 == fun t2() { @@ -26,12 +26,12 @@ fun t2() { } } --------------------- -1 NEW() -2 NEW() -3 NEW() -2 > 3 NEW(, ) -2 NEW() -{ 2 } COPY +1 : * NEW() +2 : {<: Comparable} NEW() +3 : Int NEW() +2 > 3 : Boolean NEW(, ) +2 : * NEW() +{ 2 } : * COPY ===================== == t3 == fun t3() { @@ -47,14 +47,14 @@ fun t3() { } } --------------------- -1 NEW() -{ () -> if (2 > 3) { return@l } } NEW() -@l{ () -> if (2 > 3) { return@l } } COPY -{ 1 @l{ () -> if (2 > 3) { return@l } } } COPY -2 NEW() -{ 2 } COPY -try { 1 @l{ () -> if (2 > 3) { return@l } } } finally { 2 } COPY -{ try { 1 @l{ () -> if (2 > 3) { return@l } } } finally { 2 } } COPY +1 : * NEW() +{ () -> if (2 > 3) { return@l } } : * NEW() +@l{ () -> if (2 > 3) { return@l } } : * COPY +{ 1 @l{ () -> if (2 > 3) { return@l } } } : * COPY +2 : * NEW() +{ 2 } : * COPY +try { 1 @l{ () -> if (2 > 3) { return@l } } } finally { 2 } : * COPY +{ try { 1 @l{ () -> if (2 > 3) { return@l } } } finally { 2 } } : * COPY ===================== == anonymous_0 == { () -> @@ -63,9 +63,9 @@ try { 1 @l{ () -> if (2 > 3) { return@l } } } finally { 2 } COPY } } --------------------- -2 NEW() -3 NEW() -2 > 3 NEW(, ) +2 : {<: Comparable} NEW() +3 : Int NEW() +2 > 3 : Boolean NEW(, ) ===================== == t4 == fun t4() { @@ -81,9 +81,9 @@ fun t4() { } } --------------------- -{ () -> try { 1 if (2 > 3) { return@l } } finally { 2 } } NEW() -@l{ () -> try { 1 if (2 > 3) { return@l } } finally { 2 } } COPY -{ @l{ () -> try { 1 if (2 > 3) { return@l } } finally { 2 } } } COPY +{ () -> try { 1 if (2 > 3) { return@l } } finally { 2 } } : * NEW() +@l{ () -> try { 1 if (2 > 3) { return@l } } finally { 2 } } : * COPY +{ @l{ () -> try { 1 if (2 > 3) { return@l } } finally { 2 } } } : * COPY ===================== == anonymous_1 == { () -> @@ -97,12 +97,12 @@ fun t4() { } } --------------------- -1 NEW() -2 NEW() -3 NEW() -2 > 3 NEW(, ) -2 NEW() -{ 2 } COPY +1 : * NEW() +2 : {<: Comparable} NEW() +3 : Int NEW() +2 > 3 : Boolean NEW(, ) +2 : * NEW() +{ 2 } : * COPY ===================== == t5 == fun t5() { @@ -118,13 +118,13 @@ fun t5() { } } --------------------- -true NEW() -1 NEW() -2 NEW() -3 NEW() -2 > 3 NEW(, ) -2 NEW() -{ 2 } COPY +true : * NEW() +1 : * NEW() +2 : {<: Comparable} NEW() +3 : Int NEW() +2 > 3 : Boolean NEW(, ) +2 : * NEW() +{ 2 } : * COPY ===================== == t6 == fun t6() { @@ -141,17 +141,17 @@ fun t6() { } } --------------------- -true NEW() -1 NEW() -2 NEW() -3 NEW() -2 > 3 NEW(, ) -5 NEW() -{ @l while(true) { 1 if (2 > 3) { break @l } } 5 } COPY -2 NEW() -{ 2 } COPY -try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } COPY -{ try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } } COPY +true : * NEW() +1 : * NEW() +2 : {<: Comparable} NEW() +3 : Int NEW() +2 > 3 : Boolean NEW(, ) +5 : * NEW() +{ @l while(true) { 1 if (2 > 3) { break @l } } 5 } : * COPY +2 : * NEW() +{ 2 } : * COPY +try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } : * COPY +{ try { @l while(true) { 1 if (2 > 3) { break @l } } 5 } finally { 2 } } : * COPY ===================== == t7 == fun t7() { @@ -167,13 +167,13 @@ fun t7() { } } --------------------- -true NEW() -1 NEW() -2 NEW() -3 NEW() -2 > 3 NEW(, ) -2 NEW() -{ 2 } COPY +true : * NEW() +1 : * NEW() +2 : {<: Comparable} NEW() +3 : Int NEW() +2 > 3 : Boolean NEW(, ) +2 : * NEW() +{ 2 } : * COPY ===================== == t8 == fun t8(a : Int) { @@ -189,15 +189,15 @@ fun t8(a : Int) { } } --------------------- -1 NEW() -a NEW() -1..a NEW(, ) -1 NEW() -2 NEW() -3 NEW() -2 > 3 NEW(, ) -2 NEW() -{ 2 } COPY +1 : Int NEW() +a : Int NEW() +1..a : {<: Iterable} NEW(, ) +1 : * NEW() +2 : {<: Comparable} NEW() +3 : Int NEW() +2 > 3 : Boolean NEW(, ) +2 : * NEW() +{ 2 } : * COPY ===================== == t9 == fun t9(a : Int) { @@ -214,19 +214,19 @@ fun t9(a : Int) { } } --------------------- -1 NEW() -a NEW() -1..a NEW(, ) -1 NEW() -2 NEW() -3 NEW() -2 > 3 NEW(, ) -5 NEW() -{ @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } COPY -2 NEW() -{ 2 } COPY -try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } finally { 2 } COPY -{ try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } finally { 2 } } COPY +1 : Int NEW() +a : Int NEW() +1..a : {<: Iterable} NEW(, ) +1 : * NEW() +2 : {<: Comparable} NEW() +3 : Int NEW() +2 > 3 : Boolean NEW(, ) +5 : * NEW() +{ @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } : * COPY +2 : * NEW() +{ 2 } : * COPY +try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } finally { 2 } : * COPY +{ try { @l for (i in 1..a) { 1 if (2 > 3) { continue @l } } 5 } finally { 2 } } : * COPY ===================== == t10 == fun t10(a : Int) { @@ -242,15 +242,15 @@ fun t10(a : Int) { } } --------------------- -1 NEW() -a NEW() -1..a NEW(, ) -1 NEW() -2 NEW() -3 NEW() -2 > 3 NEW(, ) -2 NEW() -{ 2 } COPY +1 : Int NEW() +a : Int NEW() +1..a : {<: Iterable} NEW(, ) +1 : * NEW() +2 : {<: Comparable} NEW() +3 : Int NEW() +2 > 3 : Boolean NEW(, ) +2 : * NEW() +{ 2 } : * COPY ===================== == t11 == fun t11() { @@ -262,8 +262,8 @@ fun t11() { } } --------------------- -1 NEW() -2 NEW() +1 : * NEW() +2 : Unit NEW() ===================== == t12 == fun t12() : Int { @@ -275,10 +275,10 @@ fun t12() : Int { } } --------------------- -1 NEW() -3 NEW() -doSmth(3) NEW() -{ doSmth(3) } COPY +1 : Int NEW() +3 : Int NEW() +doSmth(3) : * NEW() +{ doSmth(3) } : * COPY ===================== == t13 == fun t13() : Int { @@ -293,15 +293,15 @@ fun t13() : Int { } } --------------------- -1 NEW() -2 NEW() -doSmth(2) NEW() -{ doSmth(2) } COPY -3 NEW() -doSmth(3) NEW() -{ doSmth(3) } COPY -try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } COPY -{ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } } COPY +1 : Int NEW() +2 : Int NEW() +doSmth(2) : * NEW() +{ doSmth(2) } : * COPY +3 : Int NEW() +doSmth(3) : * NEW() +{ doSmth(3) } : * COPY +try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } : * COPY +{ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } finally { doSmth(3) } } : * COPY ===================== == t14 == fun t14() : Int { @@ -313,12 +313,12 @@ fun t14() : Int { } } --------------------- -1 NEW() -2 NEW() -doSmth(2) NEW() -{ doSmth(2) } COPY -try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } COPY -{ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } } COPY +1 : Int NEW() +2 : Int NEW() +doSmth(2) : * NEW() +{ doSmth(2) } : * COPY +try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } : * COPY +{ try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) } } : * COPY ===================== == t15 == fun t15() : Int { @@ -333,11 +333,11 @@ fun t15() : Int { } } --------------------- -1 NEW() -2 NEW() -3 NEW() -doSmth(3) NEW() -{ doSmth(3) } COPY +1 : Int NEW() +2 : Int NEW() +3 : Int NEW() +doSmth(3) : * NEW() +{ doSmth(3) } : * COPY ===================== == t16 == fun t16() : Int { @@ -352,15 +352,15 @@ fun t16() : Int { } } --------------------- -1 NEW() -doSmth(1) NEW() -{ doSmth(1) } COPY -2 NEW() -3 NEW() -doSmth(3) NEW() -{ doSmth(3) } COPY -try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } COPY -{ try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } } COPY +1 : Int NEW() +doSmth(1) : * NEW() +{ doSmth(1) } : * COPY +2 : Int NEW() +3 : Int NEW() +doSmth(3) : * NEW() +{ doSmth(3) } : * COPY +try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } : * COPY +{ try { doSmth(1) } catch (e: UnsupportedOperationException) { return 2 } finally { doSmth(3) } } : * COPY ===================== == doSmth == fun doSmth(i: Int) { diff --git a/compiler/testData/cfg/controlStructures/FinallyTestCopy.instructions b/compiler/testData/cfg/controlStructures/FinallyTestCopy.instructions index 10fc552489d..1fab4a10d8b 100644 --- a/compiler/testData/cfg/controlStructures/FinallyTestCopy.instructions +++ b/compiler/testData/cfg/controlStructures/FinallyTestCopy.instructions @@ -140,11 +140,11 @@ fun testCopy2() { L0: 1 2 mark({ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } }) - mark(while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } }) L2 [loop entry point]: L5 [condition entry point]: - mark(cond()) PREV:[mark(while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } }), jmp(L2 [loop entry point]), jmp(L2 [loop entry point])] + mark(cond()) PREV:[mark({ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } }), jmp(L2 [loop entry point]), jmp(L2 [loop entry point])] call(cond, cond) -> + mark(while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } }) jf(L3 [loop exit point]|) NEXT:[read (Unit), mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } })] L4 [body entry point]: 3 mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } }) @@ -256,11 +256,11 @@ L4 [afterCatches]: L3 [onExceptionToFinallyBlock]: L7 [start finally]: 3 mark({ while (cond()); }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] - mark(while (cond())) L8 [loop entry point]: L11 [condition entry point]: - mark(cond()) PREV:[mark(while (cond())), jmp(L8 [loop entry point])] + mark(cond()) PREV:[mark({ while (cond()); }), jmp(L8 [loop entry point])] call(cond, cond) -> + mark(while (cond())) jf(L9 [loop exit point]|) NEXT:[read (Unit), jmp(L8 [loop entry point])] L10 [body entry point]: jmp(L8 [loop entry point]) NEXT:[mark(cond())] @@ -270,9 +270,9 @@ L12 [finish finally]: 2 jmp(error) NEXT:[] L6 [skipFinallyToErrorBlock]: 3 mark({ while (cond()); }) PREV:[jmp(L6 [skipFinallyToErrorBlock])] - mark(while (cond())) - mark(cond()) PREV:[mark(while (cond())), jmp(copy L8 [loop entry point])] + mark(cond()) PREV:[mark({ while (cond()); }), jmp(copy L8 [loop entry point])] call(cond, cond) -> + mark(while (cond())) jf(copy L9 [loop exit point]|) NEXT:[read (Unit), jmp(copy L8 [loop entry point])] jmp(copy L8 [loop entry point]) NEXT:[mark(cond())] read (Unit) PREV:[jf(copy L9 [loop exit point]|)] @@ -311,9 +311,9 @@ L2 [onExceptionToFinallyBlock]: L4 [start finally]: 3 mark({ if(list != null) { } }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] mark(if(list != null) { }) - mark(list != null) r(list) -> r(null) -> + mark(list != null) call(!=, equals|, ) -> jf(L5|) NEXT:[read (Unit), mark({ })] 4 mark({ }) @@ -327,9 +327,9 @@ L7 [finish finally]: L3 [skipFinallyToErrorBlock]: 3 mark({ if(list != null) { } }) PREV:[jmp(L3 [skipFinallyToErrorBlock])] mark(if(list != null) { }) - mark(list != null) r(list) -> r(null) -> + mark(list != null) call(!=, equals|, ) -> jf(copy L5|) NEXT:[read (Unit), mark({ })] 4 mark({ }) diff --git a/compiler/testData/cfg/controlStructures/FinallyTestCopy.values b/compiler/testData/cfg/controlStructures/FinallyTestCopy.values index 9a622cdbac2..e49fa806b52 100644 --- a/compiler/testData/cfg/controlStructures/FinallyTestCopy.values +++ b/compiler/testData/cfg/controlStructures/FinallyTestCopy.values @@ -30,15 +30,15 @@ fun testCopy1() : Int { } } --------------------- -doSmth() NEW() -{ doSmth() } COPY -doSmth1() NEW() -{ doSmth1() } COPY -doSmth2() NEW() -{ doSmth2() } COPY -1 NEW() -try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } NEW(, , ) -{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } } COPY +doSmth() : * NEW() +{ doSmth() } : * COPY +doSmth1() : * NEW() +{ doSmth1() } : * COPY +doSmth2() : * NEW() +{ doSmth2() } : * COPY +1 : Int NEW() +try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } : * NEW(, , ) +{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } } : * COPY ===================== == testCopy2 == fun testCopy2() { @@ -59,16 +59,16 @@ fun testCopy2() { } } --------------------- -cond() NEW() -doSmth() NEW() -{ doSmth() } COPY -doSmth1() NEW() -{ doSmth1() } COPY -doSmth2() NEW() -{ doSmth2() } COPY -cond() NEW() -try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } NEW(, , ) -{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } COPY +cond() : Boolean NEW() +doSmth() : * NEW() +{ doSmth() } : * COPY +doSmth1() : * NEW() +{ doSmth1() } : * COPY +doSmth2() : * NEW() +{ doSmth2() } : * COPY +cond() : Boolean NEW() +try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } : * NEW(, , ) +{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } : * COPY ===================== == testCopy3 == fun testCopy3() { @@ -86,15 +86,15 @@ fun testCopy3() { } } --------------------- -doSmth() NEW() -{ doSmth() } COPY -doSmth1() NEW() -{ doSmth1() } COPY -doSmth2() NEW() -{ doSmth2() } COPY -cond() NEW() -try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } NEW(, , ) -{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } } COPY +doSmth() : * NEW() +{ doSmth() } : * COPY +doSmth1() : * NEW() +{ doSmth1() } : * COPY +doSmth2() : * NEW() +{ doSmth2() } : * COPY +cond() : Boolean NEW() +try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } : * NEW(, , ) +{ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } } : * COPY ===================== == doTestCopy4 == fun doTestCopy4(list: List?) : Int { @@ -107,11 +107,11 @@ fun doTestCopy4(list: List?) : Int { } } --------------------- -doSmth() NEW() -{ doSmth() } COPY -list NEW() -null NEW() -list != null NEW(, ) -try { doSmth() } finally { if(list != null) { } } COPY -{ try { doSmth() } finally { if(list != null) { } } } COPY +doSmth() : * NEW() +{ doSmth() } : * COPY +list : {<: Any?} NEW() +null : {<: Any?} NEW() +list != null : Boolean NEW(, ) +try { doSmth() } finally { if(list != null) { } } : * COPY +{ try { doSmth() } finally { if(list != null) { } } } : * COPY ===================== diff --git a/compiler/testData/cfg/controlStructures/For.instructions b/compiler/testData/cfg/controlStructures/For.instructions index 4ef25287833..399d662f15f 100644 --- a/compiler/testData/cfg/controlStructures/For.instructions +++ b/compiler/testData/cfg/controlStructures/For.instructions @@ -8,10 +8,9 @@ fun t1() { L0: 1 2 mark({ for (i in 1..2) { doSmth(i) } }) - 3 mark(for (i in 1..2) { doSmth(i) }) - mark(1..2) - r(1) -> + 3 r(1) -> r(2) -> + mark(1..2) call(.., rangeTo|, ) -> v(i) L3: @@ -20,9 +19,10 @@ L4 [loop entry point]: L5 [body entry point]: magic(1..2|) -> PREV:[jmp?(L2), jmp?(L4 [loop entry point])] w(i|) + mark(for (i in 1..2) { doSmth(i) }) 4 mark({ doSmth(i) }) - mark(doSmth(i)) r(i) -> + mark(doSmth(i)) call(doSmth, doSmth|) -> 3 jmp?(L4 [loop entry point]) NEXT:[magic(1..2|) -> , read (Unit)] L2: diff --git a/compiler/testData/cfg/controlStructures/For.values b/compiler/testData/cfg/controlStructures/For.values index c7b2ce12294..027b5496c73 100644 --- a/compiler/testData/cfg/controlStructures/For.values +++ b/compiler/testData/cfg/controlStructures/For.values @@ -5,12 +5,12 @@ fun t1() { } } --------------------- -1 NEW() -2 NEW() -1..2 NEW(, ) -i NEW() -doSmth(i) NEW() -{ doSmth(i) } COPY +1 : Int NEW() +2 : Int NEW() +1..2 : {<: Iterable} NEW(, ) +i : Int NEW() +doSmth(i) : * NEW() +{ doSmth(i) } : * COPY ===================== == doSmth == fun doSmth(i: Int) {} diff --git a/compiler/testData/cfg/controlStructures/If.instructions b/compiler/testData/cfg/controlStructures/If.instructions index c99cbe8b258..3393470ce8a 100644 --- a/compiler/testData/cfg/controlStructures/If.instructions +++ b/compiler/testData/cfg/controlStructures/If.instructions @@ -30,12 +30,12 @@ L0: mark("s") r("s") -> w(u|) - 2 jmp(L3) NEXT:[mark(doSmth(u))] + 2 jmp(L3) NEXT:[r(u) -> ] L2: read (Unit) PREV:[jf(L2|)] L3: - mark(doSmth(u)) PREV:[jmp(L3), read (Unit)] - r(u) -> + r(u) -> PREV:[jmp(L3), read (Unit)] + mark(doSmth(u)) call(doSmth, doSmth|) -> v(var r: String) mark(if (b) { r = "s" } else { r = "t" }) @@ -45,15 +45,15 @@ L3: mark("s") r("s") -> w(r|) - 2 jmp(L5) NEXT:[mark(doSmth(r))] + 2 jmp(L5) NEXT:[r(r) -> ] L4: 3 mark({ r = "t" }) PREV:[jf(L4|)] mark("t") r("t") -> w(r|) L5: - 2 mark(doSmth(r)) PREV:[jmp(L5), w(r|)] - r(r) -> + 2 r(r) -> PREV:[jmp(L5), w(r|)] + mark(doSmth(r)) call(doSmth, doSmth|) -> L1: 1 NEXT:[] @@ -88,12 +88,12 @@ L0: jf(L2|) NEXT:[read (Unit), mark({ return; })] 3 mark({ return; }) ret L1 NEXT:[] -- 2 jmp(L3) NEXT:[mark(doSmth(i))] PREV:[] +- 2 jmp(L3) NEXT:[r(i) -> ] PREV:[] L2: read (Unit) PREV:[jf(L2|)] L3: - mark(doSmth(i)) r(i) -> + mark(doSmth(i)) call(doSmth, doSmth|) -> mark(if (i is Int) { return; }) mark(i is Int) diff --git a/compiler/testData/cfg/controlStructures/If.values b/compiler/testData/cfg/controlStructures/If.values index f0055a9467d..e2c4f2cf276 100644 --- a/compiler/testData/cfg/controlStructures/If.values +++ b/compiler/testData/cfg/controlStructures/If.values @@ -16,16 +16,16 @@ fun t1(b: Boolean) { doSmth(r) } --------------------- -b NEW() -"s" NEW() -u NEW() -doSmth(u) NEW() -b NEW() -"s" NEW() -"t" NEW() -r NEW() -doSmth(r) NEW() -{ var u: String if (b) { u = "s" } doSmth(u) var r: String if (b) { r = "s" } else { r = "t" } doSmth(r) } COPY +b : Boolean NEW() +"s" : String NEW() +u : String NEW() +doSmth(u) : * NEW() +b : Boolean NEW() +"s" : String NEW() +"t" : String NEW() +r : String NEW() +doSmth(r) : * NEW() +{ var u: String if (b) { u = "s" } doSmth(u) var r: String if (b) { r = "s" } else { r = "t" } doSmth(r) } : * COPY ===================== == t2 == fun t2(b: Boolean) { @@ -39,12 +39,12 @@ fun t2(b: Boolean) { } } --------------------- -3 NEW() -b NEW() -i NEW() -doSmth(i) NEW() -i NEW() -i is Int NEW() +3 : Int NEW() +b : Boolean NEW() +i : String NEW() +doSmth(i) : * NEW() +i : * NEW() +i is Int : Boolean NEW() ===================== == doSmth == fun doSmth(s: String) {} diff --git a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions index 9d727a8c2f8..452cda3860e 100644 --- a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions +++ b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.instructions @@ -8,18 +8,18 @@ fun main() { L0: 1 2 mark({ while(0 > 1) { 2 } }) - mark(while(0 > 1) { 2 }) L2 [loop entry point]: L5 [condition entry point]: - mark(0 > 1) PREV:[mark(while(0 > 1) { 2 }), jmp(L2 [loop entry point])] - r(0) -> + r(0) -> PREV:[mark({ while(0 > 1) { 2 } }), jmp(L2 [loop entry point])] r(1) -> + mark(0 > 1) call(>, compareTo|, ) -> + mark(while(0 > 1) { 2 }) jf(L3 [loop exit point]|) NEXT:[read (Unit), mark({ 2 })] L4 [body entry point]: 3 mark({ 2 }) r(2) -> - 2 jmp(L2 [loop entry point]) NEXT:[mark(0 > 1)] + 2 jmp(L2 [loop entry point]) NEXT:[r(0) -> ] L3 [loop exit point]: read (Unit) PREV:[jf(L3 [loop exit point]|)] L1: @@ -44,9 +44,9 @@ L4 [body entry point]: mark({return}) ret L1 NEXT:[] L5 [condition entry point]: -- mark(0 > 1) PREV:[] - r(0) -> PREV:[] - r(1) -> PREV:[] +- mark(0 > 1) PREV:[] - call(>, compareTo|, ) -> PREV:[] - jt(L2 [loop entry point]|) NEXT:[read (Unit), mark({return})] PREV:[] L3 [loop exit point]: diff --git a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.values b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.values index b01dad9a5e4..b6eaafa0d7c 100644 --- a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.values +++ b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.values @@ -5,11 +5,11 @@ fun main() { } } --------------------- -0 NEW() -1 NEW() -0 > 1 NEW(, ) -2 NEW() -{ 2 } COPY +0 : {<: Comparable} NEW() +1 : Int NEW() +0 > 1 : Boolean NEW(, ) +2 : * NEW() +{ 2 } : * COPY ===================== == dowhile == fun dowhile() { @@ -17,7 +17,7 @@ fun dowhile() { while(0 > 1) } --------------------- -0 NEW() -1 NEW() -0 > 1 NEW(, ) +0 : * NEW() +1 : * NEW() +0 > 1 : * NEW(, ) ===================== diff --git a/compiler/testData/cfg/controlStructures/returnsInWhen.values b/compiler/testData/cfg/controlStructures/returnsInWhen.values index 6fb7648cce6..f1835c8c05d 100644 --- a/compiler/testData/cfg/controlStructures/returnsInWhen.values +++ b/compiler/testData/cfg/controlStructures/returnsInWhen.values @@ -5,6 +5,6 @@ fun illegalWhenBlock(a: Any): Any { } } --------------------- -a NEW() -a NEW() +a : * NEW() +a : {<: Any} NEW() ===================== diff --git a/compiler/testData/cfg/conventions/bothReceivers.instructions b/compiler/testData/cfg/conventions/bothReceivers.instructions new file mode 100644 index 00000000000..ee01e13b419 --- /dev/null +++ b/compiler/testData/cfg/conventions/bothReceivers.instructions @@ -0,0 +1,65 @@ +== Bar == +class Bar { +} +--------------------- +L0: + 1 +L1: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== Foo == +class Foo() { + fun Bar.invoke() {} +} +--------------------- +L0: + 1 +L1: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== invoke == +fun Bar.invoke() {} +--------------------- +L0: + 1 + 2 mark({}) + read (Unit) +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== foobar == +fun foobar(f: Foo) { + Bar().f() +} +--------------------- +L0: + 1 + v(f: Foo) + magic(f: Foo) -> + w(f|) + 2 mark({ Bar().f() }) + mark(Bar().f()) + r(f) -> + mark(Bar()) + call(Bar, ) -> + mark(f()) + call(f, invoke|, ) -> +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== diff --git a/compiler/testData/cfg/conventions/bothReceivers.kt b/compiler/testData/cfg/conventions/bothReceivers.kt new file mode 100644 index 00000000000..1ad462cb71d --- /dev/null +++ b/compiler/testData/cfg/conventions/bothReceivers.kt @@ -0,0 +1,10 @@ +class Bar { +} + +class Foo() { + fun Bar.invoke() {} +} + +fun foobar(f: Foo) { + Bar().f() +} \ No newline at end of file diff --git a/compiler/testData/cfg/conventions/bothReceivers.values b/compiler/testData/cfg/conventions/bothReceivers.values new file mode 100644 index 00000000000..0e2db937727 --- /dev/null +++ b/compiler/testData/cfg/conventions/bothReceivers.values @@ -0,0 +1,26 @@ +== Bar == +class Bar { +} +--------------------- +===================== +== Foo == +class Foo() { + fun Bar.invoke() {} +} +--------------------- +===================== +== invoke == +fun Bar.invoke() {} +--------------------- +===================== +== foobar == +fun foobar(f: Foo) { + Bar().f() +} +--------------------- +Bar() : Bar NEW() +f : Foo NEW() +f() : * NEW(, ) +Bar().f() : * COPY +{ Bar().f() } : * COPY +===================== \ No newline at end of file diff --git a/compiler/testData/cfg/conventions/equals.instructions b/compiler/testData/cfg/conventions/equals.instructions index 5151be2fd13..d8431a598c6 100644 --- a/compiler/testData/cfg/conventions/equals.instructions +++ b/compiler/testData/cfg/conventions/equals.instructions @@ -14,9 +14,9 @@ L0: w(b|) 2 mark({ if (a == b) { } }) mark(if (a == b) { }) - mark(a == b) r(a) -> r(b) -> + mark(a == b) call(==, equals|, ) -> jf(L2|) NEXT:[read (Unit), mark({ })] 3 mark({ }) diff --git a/compiler/testData/cfg/conventions/equals.values b/compiler/testData/cfg/conventions/equals.values index fde14f3d634..9d4a5bf3270 100644 --- a/compiler/testData/cfg/conventions/equals.values +++ b/compiler/testData/cfg/conventions/equals.values @@ -4,7 +4,7 @@ fun foo(a: Int, b: Int) { } } --------------------- -a NEW() -b NEW() -a == b NEW(, ) +a : OR{{<: Any}, {<: Any}} NEW() +b : {<: Any?} NEW() +a == b : Boolean NEW(, ) ===================== diff --git a/compiler/testData/cfg/conventions/incrementAtTheEnd.instructions b/compiler/testData/cfg/conventions/incrementAtTheEnd.instructions index 7ea1808d900..030decbcc89 100644 --- a/compiler/testData/cfg/conventions/incrementAtTheEnd.instructions +++ b/compiler/testData/cfg/conventions/incrementAtTheEnd.instructions @@ -10,8 +10,8 @@ L0: v(var i = 1) r(1) -> w(i|) - mark(i++) r(i) -> + mark(i++) call(++, inc|) -> w(i|) L1: diff --git a/compiler/testData/cfg/conventions/incrementAtTheEnd.values b/compiler/testData/cfg/conventions/incrementAtTheEnd.values index 708871cea55..daed10577df 100644 --- a/compiler/testData/cfg/conventions/incrementAtTheEnd.values +++ b/compiler/testData/cfg/conventions/incrementAtTheEnd.values @@ -4,6 +4,8 @@ fun foo() { i++ } --------------------- -1 NEW() -i NEW() +1 : Int NEW() +i : Int NEW() +i++ : Int COPY +{ var i = 1 i++ } : Int COPY ===================== diff --git a/compiler/testData/cfg/conventions/invoke.instructions b/compiler/testData/cfg/conventions/invoke.instructions index cababa1643f..9c282e0116d 100644 --- a/compiler/testData/cfg/conventions/invoke.instructions +++ b/compiler/testData/cfg/conventions/invoke.instructions @@ -9,8 +9,8 @@ L0: magic(f: () -> Unit) -> w(f|) 2 mark({ f() }) - mark(f()) r(f) -> + mark(f()) call(f, invoke|) -> L1: 1 NEXT:[] diff --git a/compiler/testData/cfg/conventions/invoke.values b/compiler/testData/cfg/conventions/invoke.values index 448531f5c64..02c3e5b3466 100644 --- a/compiler/testData/cfg/conventions/invoke.values +++ b/compiler/testData/cfg/conventions/invoke.values @@ -3,7 +3,7 @@ fun foo(f: () -> Unit) { f() } --------------------- -f NEW() -f() NEW() -{ f() } COPY +f : {<: () -> Unit} NEW() +f() : * NEW() +{ f() } : * COPY ===================== diff --git a/compiler/testData/cfg/conventions/notEqual.instructions b/compiler/testData/cfg/conventions/notEqual.instructions index 83685976b4b..98d8a17ae84 100644 --- a/compiler/testData/cfg/conventions/notEqual.instructions +++ b/compiler/testData/cfg/conventions/notEqual.instructions @@ -13,9 +13,9 @@ L0: w(b|) 2 mark({ if (a != b) {} }) mark(if (a != b) {}) - mark(a != b) r(a) -> r(b) -> + mark(a != b) call(!=, equals|, ) -> jf(L2|) NEXT:[read (Unit), mark({})] 3 mark({}) diff --git a/compiler/testData/cfg/conventions/notEqual.values b/compiler/testData/cfg/conventions/notEqual.values index 0ec5fe6e8a7..5f758f0157a 100644 --- a/compiler/testData/cfg/conventions/notEqual.values +++ b/compiler/testData/cfg/conventions/notEqual.values @@ -3,7 +3,7 @@ fun neq(a: Int, b: Int) { if (a != b) {} } --------------------- -a NEW() -b NEW() -a != b NEW(, ) +a : OR{{<: Any}, {<: Any}} NEW() +b : {<: Any?} NEW() +a != b : Boolean NEW(, ) ===================== diff --git a/compiler/testData/cfg/deadCode/DeadCode.values b/compiler/testData/cfg/deadCode/DeadCode.values index 994dd1d105f..addf7ec3995 100644 --- a/compiler/testData/cfg/deadCode/DeadCode.values +++ b/compiler/testData/cfg/deadCode/DeadCode.values @@ -4,7 +4,7 @@ fun test() { test() } --------------------- -Exception() NEW() -test() NEW() -{ throw Exception() test() } COPY +Exception() : {<: Throwable} NEW() +test() : * NEW() +{ throw Exception() test() } : * COPY ===================== diff --git a/compiler/testData/cfg/deadCode/returnInElvis.instructions b/compiler/testData/cfg/deadCode/returnInElvis.instructions index dc75bf6ae3f..a8837e2cd21 100644 --- a/compiler/testData/cfg/deadCode/returnInElvis.instructions +++ b/compiler/testData/cfg/deadCode/returnInElvis.instructions @@ -7,6 +7,7 @@ L0: 1 2 mark({ return ?: null }) ret L1 NEXT:[] +- mark(return ?: null) PREV:[] - jt(L2) NEXT:[r(null) -> , ] PREV:[] - r(null) -> PREV:[] L1: diff --git a/compiler/testData/cfg/deadCode/returnInElvis.values b/compiler/testData/cfg/deadCode/returnInElvis.values index a2105a61f56..0a2dabc4721 100644 --- a/compiler/testData/cfg/deadCode/returnInElvis.values +++ b/compiler/testData/cfg/deadCode/returnInElvis.values @@ -3,7 +3,7 @@ fun foo() { return ?: null } --------------------- -null NEW() -return ?: null COPY -{ return ?: null } COPY +null : * NEW() +return ?: null : * COPY +{ return ?: null } : * COPY ===================== diff --git a/compiler/testData/cfg/deadCode/stringTemplate.values b/compiler/testData/cfg/deadCode/stringTemplate.values index b4c1c1b7c16..280634698cd 100644 --- a/compiler/testData/cfg/deadCode/stringTemplate.values +++ b/compiler/testData/cfg/deadCode/stringTemplate.values @@ -3,8 +3,8 @@ fun test() { "${throw Exception()} ${1}" } --------------------- -Exception() NEW() -1 NEW() -"${throw Exception()} ${1}" NEW() -{ "${throw Exception()} ${1}" } COPY +Exception() : {<: Throwable} NEW() +1 : * NEW() +"${throw Exception()} ${1}" : * NEW() +{ "${throw Exception()} ${1}" } : * COPY ===================== diff --git a/compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.values b/compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.values index 1f09331a566..886da7ea362 100644 --- a/compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.values +++ b/compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.values @@ -15,7 +15,7 @@ class AnonymousInitializers() { } } --------------------- -34 NEW() -12 NEW() -13 NEW() +34 : Int NEW() +12 : Int NEW() +13 : Int NEW() ===================== diff --git a/compiler/testData/cfg/declarations/functionLiterals/unusedFunctionLiteral.values b/compiler/testData/cfg/declarations/functionLiterals/unusedFunctionLiteral.values index e5a74bb024f..5ac4b35aefe 100644 --- a/compiler/testData/cfg/declarations/functionLiterals/unusedFunctionLiteral.values +++ b/compiler/testData/cfg/declarations/functionLiterals/unusedFunctionLiteral.values @@ -3,8 +3,8 @@ fun foo() { {} } --------------------- -{} NEW() -{ {} } COPY +{} : * NEW() +{ {} } : * COPY ===================== == anonymous_0 == {} diff --git a/compiler/testData/cfg/declarations/functions/FailFunction.values b/compiler/testData/cfg/declarations/functions/FailFunction.values index 062ee86dcf5..7a6b3c52016 100644 --- a/compiler/testData/cfg/declarations/functions/FailFunction.values +++ b/compiler/testData/cfg/declarations/functions/FailFunction.values @@ -3,6 +3,6 @@ fun fail() : Nothing { throw java.lang.RuntimeException() } --------------------- -RuntimeException() NEW() -java.lang.RuntimeException() COPY +RuntimeException() : {<: Throwable} NEW() +java.lang.RuntimeException() : {<: Throwable} COPY ===================== diff --git a/compiler/testData/cfg/declarations/functions/typeParameter.values b/compiler/testData/cfg/declarations/functions/typeParameter.values index 4ee00400258..ab80f5a4ee4 100644 --- a/compiler/testData/cfg/declarations/functions/typeParameter.values +++ b/compiler/testData/cfg/declarations/functions/typeParameter.values @@ -3,6 +3,6 @@ fun foo() { T } --------------------- -T NEW() -{ T } COPY +T : * NEW() +{ T } : * COPY ===================== diff --git a/compiler/testData/cfg/declarations/local/LocalDeclarations.values b/compiler/testData/cfg/declarations/local/LocalDeclarations.values index 4972ccbbe1b..9c4fe5cf211 100644 --- a/compiler/testData/cfg/declarations/local/LocalDeclarations.values +++ b/compiler/testData/cfg/declarations/local/LocalDeclarations.values @@ -17,7 +17,7 @@ class C() { } } --------------------- -1 NEW() +1 : Int NEW() ===================== == doSmth == fun doSmth(i: Int) {} @@ -33,8 +33,8 @@ fun test1() { } } --------------------- -1 NEW() -object { val x : Int { $x = 1 } } NEW() +1 : Int NEW() +object { val x : Int { $x = 1 } } : NEW() ===================== == O == object O { @@ -44,7 +44,7 @@ object O { } } --------------------- -1 NEW() +1 : Int NEW() ===================== == test2 == fun test2() { @@ -54,9 +54,9 @@ fun test2() { } } --------------------- -1 NEW() -b NEW() -object { val x = b } NEW() +1 : Int NEW() +b : Int NEW() +object { val x = b } : NEW() ===================== == test3 == fun test3() { @@ -68,14 +68,14 @@ fun test3() { } } --------------------- -object { val y : Int fun inner_bar() { y = 10 } } NEW() +object { val y : Int fun inner_bar() { y = 10 } } : NEW() ===================== == inner_bar == fun inner_bar() { y = 10 } --------------------- -10 NEW() +10 : Int NEW() ===================== == test4 == fun test4() { @@ -91,15 +91,15 @@ fun test4() { } } --------------------- -1 NEW() -object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } } NEW() +1 : Int NEW() +object { val x : Int val y : Int { $x = 1 } fun ggg() { y = 10 } } : NEW() ===================== == ggg == fun ggg() { y = 10 } --------------------- -10 NEW() +10 : Int NEW() ===================== == test5 == fun test5() { @@ -117,21 +117,21 @@ fun test5() { } } --------------------- -1 NEW() -2 NEW() -object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } } NEW() +1 : Int NEW() +2 : Int NEW() +object { var x = 1 { $x = 2 } fun foo() { x = 3 } fun bar() { x = 4 } } : NEW() ===================== == foo == fun foo() { x = 3 } --------------------- -3 NEW() +3 : Int NEW() ===================== == bar == fun bar() { x = 4 } --------------------- -4 NEW() +4 : Int NEW() ===================== diff --git a/compiler/testData/cfg/declarations/local/ObjectExpression.instructions b/compiler/testData/cfg/declarations/local/ObjectExpression.instructions index 806b47a8c84..11cf0c848e9 100644 --- a/compiler/testData/cfg/declarations/local/ObjectExpression.instructions +++ b/compiler/testData/cfg/declarations/local/ObjectExpression.instructions @@ -70,8 +70,8 @@ L0: r(object : A by b {}) -> w(o|) mark(o.foo()) - mark(foo()) r(o) -> + mark(foo()) call(foo, foo|) -> ret(*|) L1 L1: diff --git a/compiler/testData/cfg/declarations/local/ObjectExpression.values b/compiler/testData/cfg/declarations/local/ObjectExpression.values index deaf3419903..bf8c6041316 100644 --- a/compiler/testData/cfg/declarations/local/ObjectExpression.values +++ b/compiler/testData/cfg/declarations/local/ObjectExpression.values @@ -17,7 +17,7 @@ class B : A { == foo == override fun foo() = 10 --------------------- -10 NEW() +10 : Int NEW() ===================== == foo == fun foo(b: B) : Int { @@ -25,9 +25,9 @@ fun foo(b: B) : Int { return o.foo() } --------------------- -b NEW() -object : A by b {} NEW() -o NEW() -foo() NEW() -o.foo() COPY +b : * NEW() +object : A by b {} : NEW() +o : {<: A} NEW() +foo() : Int NEW() +o.foo() : Int COPY ===================== diff --git a/compiler/testData/cfg/declarations/local/localClass.values b/compiler/testData/cfg/declarations/local/localClass.values index 901eba15d72..4b9ec1b16cd 100644 --- a/compiler/testData/cfg/declarations/local/localClass.values +++ b/compiler/testData/cfg/declarations/local/localClass.values @@ -21,12 +21,12 @@ fun f() { } } --------------------- -"" NEW() +"" : String NEW() ===================== == loc == fun loc() { val x3 = "" } --------------------- -"" NEW() +"" : String NEW() ===================== diff --git a/compiler/testData/cfg/declarations/local/localProperty.values b/compiler/testData/cfg/declarations/local/localProperty.values index 3f3f9bf7ac5..bd5c69a29c0 100644 --- a/compiler/testData/cfg/declarations/local/localProperty.values +++ b/compiler/testData/cfg/declarations/local/localProperty.values @@ -16,5 +16,5 @@ get() { return b } --------------------- -b NEW() +b : Int NEW() ===================== diff --git a/compiler/testData/cfg/declarations/multiDeclaration/MultiDecl.values b/compiler/testData/cfg/declarations/multiDeclaration/MultiDecl.values index 0cf5a4b0acd..99a44889fa0 100644 --- a/compiler/testData/cfg/declarations/multiDeclaration/MultiDecl.values +++ b/compiler/testData/cfg/declarations/multiDeclaration/MultiDecl.values @@ -8,12 +8,12 @@ class C { == component1 == fun component1() = 1 --------------------- -1 NEW() +1 : Int NEW() ===================== == component2 == fun component2() = 2 --------------------- -2 NEW() +2 : Int NEW() ===================== == test == fun test(c: C) { @@ -21,8 +21,8 @@ fun test(c: C) { val d = 1 } --------------------- -a NEW() -b NEW() -c NEW() -1 NEW() +a : Int NEW() +b : Int NEW() +c : C NEW() +1 : Int NEW() ===================== diff --git a/compiler/testData/cfg/declarations/multiDeclaration/multiDeclarationWithError.values b/compiler/testData/cfg/declarations/multiDeclaration/multiDeclarationWithError.values index 71f56d9b567..cad29edf6e3 100644 --- a/compiler/testData/cfg/declarations/multiDeclaration/multiDeclarationWithError.values +++ b/compiler/testData/cfg/declarations/multiDeclaration/multiDeclarationWithError.values @@ -4,7 +4,7 @@ fun foo(x: Int) { a } --------------------- -x NEW() -a NEW() -{ val (a, b) = x a } COPY +x : * NEW() +a : * NEW() +{ val (a, b) = x a } : * COPY ===================== diff --git a/compiler/testData/cfg/declarations/properties/DelegatedProperty.values b/compiler/testData/cfg/declarations/properties/DelegatedProperty.values index 0cb0fefa23e..7197e993c66 100644 --- a/compiler/testData/cfg/declarations/properties/DelegatedProperty.values +++ b/compiler/testData/cfg/declarations/properties/DelegatedProperty.values @@ -7,15 +7,15 @@ class Delegate { == get == fun get(_this: Any, p: PropertyMetadata): Int = 0 --------------------- -0 NEW() +0 : Int NEW() ===================== == a == val a = Delegate() --------------------- -Delegate() NEW() +Delegate() : Delegate NEW() ===================== == b == val b by a --------------------- -a NEW() +a : * NEW() ===================== diff --git a/compiler/testData/cfg/declarations/properties/backingFieldAccess.values b/compiler/testData/cfg/declarations/properties/backingFieldAccess.values index 1b32ec1b88e..163de356aa2 100644 --- a/compiler/testData/cfg/declarations/properties/backingFieldAccess.values +++ b/compiler/testData/cfg/declarations/properties/backingFieldAccess.values @@ -8,6 +8,6 @@ class C { } } --------------------- -$a NEW() -{ $a } COPY +$a : * NEW() +{ $a } : * COPY ===================== diff --git a/compiler/testData/cfg/declarations/properties/backingFieldQualifiedWithThis.instructions b/compiler/testData/cfg/declarations/properties/backingFieldQualifiedWithThis.instructions index 7f0b2a4f09d..2f8dbad732c 100644 --- a/compiler/testData/cfg/declarations/properties/backingFieldQualifiedWithThis.instructions +++ b/compiler/testData/cfg/declarations/properties/backingFieldQualifiedWithThis.instructions @@ -19,12 +19,12 @@ fun foo() = "foo" + this.$bar --------------------- L0: 1 - mark("foo" + this.$bar) mark("foo") r("foo") -> mark(this.$bar) r(this) -> r($bar|) -> + mark("foo" + this.$bar) call(+, plus|, ) -> L1: NEXT:[] diff --git a/compiler/testData/cfg/declarations/properties/backingFieldQualifiedWithThis.values b/compiler/testData/cfg/declarations/properties/backingFieldQualifiedWithThis.values index 1e5f253264f..6c6f52e2a37 100644 --- a/compiler/testData/cfg/declarations/properties/backingFieldQualifiedWithThis.values +++ b/compiler/testData/cfg/declarations/properties/backingFieldQualifiedWithThis.values @@ -8,10 +8,10 @@ abstract class Bar { == foo == fun foo() = "foo" + this.$bar --------------------- -"foo" NEW() -this COPY -this NEW() -$bar NEW() -this.$bar COPY -"foo" + this.$bar NEW(, ) +"foo" : String NEW() +this : {<: Bar} COPY +this : {<: Bar} NEW() +$bar : {<: Any?} NEW() +this.$bar : {<: Any?} COPY +"foo" + this.$bar : String NEW(, ) ===================== diff --git a/compiler/testData/cfg/expressions/Assignments.instructions b/compiler/testData/cfg/expressions/Assignments.instructions index f2c24747477..a9368b3d1f3 100644 --- a/compiler/testData/cfg/expressions/Assignments.instructions +++ b/compiler/testData/cfg/expressions/Assignments.instructions @@ -37,9 +37,9 @@ L0: w(x|) r(2) -> w(x|) - mark(x += 2) r(x) -> r(2) -> + mark(x += 2) call(+=, plus|, ) -> w(x|) mark(if (true) 1 else 2) @@ -73,11 +73,11 @@ L5: r(t) -> r(1) -> w(t.x|, ) - mark(t.x += 1) mark(t.x) r(t) -> r(x|) -> r(1) -> + mark(t.x += 1) call(+=, plus|, ) -> r(t) -> w(t.x|, ) diff --git a/compiler/testData/cfg/expressions/Assignments.values b/compiler/testData/cfg/expressions/Assignments.values index 122e8516b37..f532d04aa5c 100644 --- a/compiler/testData/cfg/expressions/Assignments.values +++ b/compiler/testData/cfg/expressions/Assignments.values @@ -20,25 +20,28 @@ fun assignments() : Unit { t.x += 1 } --------------------- -1 NEW() -2 NEW() -x NEW() -2 NEW() -true NEW() -1 NEW() -2 NEW() -if (true) 1 else 2 NEW(, ) -true NEW() -false NEW() -true && false NEW(, ) -false NEW() -true NEW() -false && true NEW(, ) -Test() NEW() -t NEW() -1 NEW() -t NEW() -x NEW() -t.x COPY -1 NEW() +1 : Int NEW() +2 : Int NEW() +x : Int NEW() +2 : Int NEW() +x += 2 : Int NEW(, ) +true : Boolean NEW() +1 : Int NEW() +2 : Int NEW() +if (true) 1 else 2 : Int NEW(, ) +true : Boolean NEW() +false : Boolean NEW() +true && false : Boolean NEW(, ) +false : Boolean NEW() +true : Boolean NEW() +false && true : Boolean NEW(, ) +Test() : Test NEW() +t : Test NEW() +1 : Int NEW() +t : Test NEW() +x : Int NEW() +t.x : Int COPY +1 : Int NEW() +t.x += 1 : Int NEW(, ) +{ var x = 1 x = 2 x += 2 x = if (true) 1 else 2 val y = true && false val z = false && true val t = Test(); t.x = 1 t.x += 1 } : Int COPY ===================== diff --git a/compiler/testData/cfg/expressions/LazyBooleans.instructions b/compiler/testData/cfg/expressions/LazyBooleans.instructions index 3d5bb8a9941..f7e99fd1981 100644 --- a/compiler/testData/cfg/expressions/LazyBooleans.instructions +++ b/compiler/testData/cfg/expressions/LazyBooleans.instructions @@ -40,48 +40,50 @@ L3: r(3) -> mark(if (a && b) 5 else 6) r(a) -> - jf(L4|) NEXT:[jf(L5), r(b) -> ] + jf(L4|) NEXT:[magic(a && b|, ) -> , r(b) -> ] r(b) -> L4: - jf(L5) NEXT:[r(6) -> , r(5) -> ] PREV:[jf(L4|), r(b) -> ] - r(5) -> - jmp(L6) NEXT:[merge(if (a && b) 5 else 6|, ) -> ] + magic(a && b|, ) -> PREV:[jf(L4|), r(b) -> ] + jf(L5|) NEXT:[r(6) -> , r(5) -> ] + r(5) -> + jmp(L6) NEXT:[merge(if (a && b) 5 else 6|, ) -> ] L5: - r(6) -> PREV:[jf(L5)] + r(6) -> PREV:[jf(L5|)] L6: - merge(if (a && b) 5 else 6|, ) -> PREV:[jmp(L6), r(6) -> ] - r(7) -> + merge(if (a && b) 5 else 6|, ) -> PREV:[jmp(L6), r(6) -> ] + r(7) -> mark(if (a || b) 8 else 9) - r(a) -> - jt(L7|) NEXT:[r(b) -> , jf(L8)] - r(b) -> + r(a) -> + jt(L7|) NEXT:[r(b) -> , magic(a || b|, ) -> ] + r(b) -> L7: - jf(L8) NEXT:[r(9) -> , r(8) -> ] PREV:[jt(L7|), r(b) -> ] - r(8) -> - jmp(L9) NEXT:[merge(if (a || b) 8 else 9|, ) -> ] + magic(a || b|, ) -> PREV:[jt(L7|), r(b) -> ] + jf(L8|) NEXT:[r(9) -> , r(8) -> ] + r(8) -> + jmp(L9) NEXT:[merge(if (a || b) 8 else 9|, ) -> ] L8: - r(9) -> PREV:[jf(L8)] + r(9) -> PREV:[jf(L8|)] L9: - merge(if (a || b) 8 else 9|, ) -> PREV:[jmp(L9), r(9) -> ] - r(10) -> + merge(if (a || b) 8 else 9|, ) -> PREV:[jmp(L9), r(9) -> ] + r(10) -> mark(if (a) 11) - r(a) -> - jf(L10|) NEXT:[read (Unit), r(11) -> ] - r(11) -> - jmp(L11) NEXT:[r(12) -> ] + r(a) -> + jf(L10|) NEXT:[read (Unit), r(11) -> ] + r(11) -> + jmp(L11) NEXT:[r(12) -> ] L10: - read (Unit) PREV:[jf(L10|)] + read (Unit) PREV:[jf(L10|)] L11: - r(12) -> PREV:[jmp(L11), read (Unit)] + r(12) -> PREV:[jmp(L11), read (Unit)] mark(if (a) else 13) - r(a) -> - jf(L12|) NEXT:[r(13) -> , read (Unit)] + r(a) -> + jf(L12|) NEXT:[r(13) -> , read (Unit)] read (Unit) - jmp(L13) NEXT:[r(14) -> ] + jmp(L13) NEXT:[r(14) -> ] L12: - r(13) -> PREV:[jf(L12|)] + r(13) -> PREV:[jf(L12|)] L13: - r(14) -> PREV:[jmp(L13), r(13) -> ] + r(14) -> PREV:[jmp(L13), r(13) -> ] L1: 1 NEXT:[] error: diff --git a/compiler/testData/cfg/expressions/LazyBooleans.values b/compiler/testData/cfg/expressions/LazyBooleans.values index 875bf5a3649..b432c87df86 100644 --- a/compiler/testData/cfg/expressions/LazyBooleans.values +++ b/compiler/testData/cfg/expressions/LazyBooleans.values @@ -17,32 +17,34 @@ fun lazyBooleans(a : Boolean, b : Boolean) : Unit { 14 } --------------------- -a NEW() -1 NEW() -{ 1 } COPY -2 NEW() -{ 2 } COPY -if (a) { 1 } else { 2 } NEW(, ) -3 NEW() -a NEW() -b NEW() -5 NEW() -6 NEW() -if (a && b) 5 else 6 NEW(, ) -7 NEW() -a NEW() -b NEW() -8 NEW() -9 NEW() -if (a || b) 8 else 9 NEW(, ) -10 NEW() -a NEW() -11 NEW() -if (a) 11 COPY -12 NEW() -a NEW() -13 NEW() -if (a) else 13 COPY -14 NEW() -{ if (a) { 1 } else { 2 } 3 if (a && b) 5 else 6 7 if (a || b) 8 else 9 10 if (a) 11 12 if (a) else 13 14 } COPY +a : Boolean NEW() +1 : * NEW() +{ 1 } : * COPY +2 : * NEW() +{ 2 } : * COPY +if (a) { 1 } else { 2 } : * NEW(, ) +3 : * NEW() +a : Boolean NEW() +b : Boolean NEW() +a && b : Boolean NEW(, ) +5 : * NEW() +6 : * NEW() +if (a && b) 5 else 6 : * NEW(, ) +7 : * NEW() +a : Boolean NEW() +b : Boolean NEW() +a || b : Boolean NEW(, ) +8 : * NEW() +9 : * NEW() +if (a || b) 8 else 9 : * NEW(, ) +10 : * NEW() +a : Boolean NEW() +11 : * NEW() +if (a) 11 : * COPY +12 : * NEW() +a : Boolean NEW() +13 : * NEW() +if (a) else 13 : * COPY +14 : * NEW() +{ if (a) { 1 } else { 2 } 3 if (a && b) 5 else 6 7 if (a || b) 8 else 9 10 if (a) 11 12 if (a) else 13 14 } : * COPY ===================== diff --git a/compiler/testData/cfg/expressions/ReturnFromExpression.values b/compiler/testData/cfg/expressions/ReturnFromExpression.values index fefb44006b9..dc871c3aa57 100644 --- a/compiler/testData/cfg/expressions/ReturnFromExpression.values +++ b/compiler/testData/cfg/expressions/ReturnFromExpression.values @@ -3,8 +3,8 @@ fun blockAndAndMismatch() : Boolean { false || (return false) } --------------------- -false NEW() -false NEW() -false || (return false) NEW() -{ false || (return false) } COPY +false : Boolean NEW() +false : Boolean NEW() +false || (return false) : * NEW() +{ false || (return false) } : * COPY ===================== diff --git a/compiler/testData/cfg/expressions/assignmentToThis.values b/compiler/testData/cfg/expressions/assignmentToThis.values index 45d0ff07d35..2571d44967f 100644 --- a/compiler/testData/cfg/expressions/assignmentToThis.values +++ b/compiler/testData/cfg/expressions/assignmentToThis.values @@ -3,5 +3,5 @@ fun Int.bar(c: C) { this = c } --------------------- -c NEW() +c : * NEW() ===================== diff --git a/compiler/testData/cfg/expressions/chainedQualifiedExpression.instructions b/compiler/testData/cfg/expressions/chainedQualifiedExpression.instructions index dd79aa7acbc..427a9c29ff2 100644 --- a/compiler/testData/cfg/expressions/chainedQualifiedExpression.instructions +++ b/compiler/testData/cfg/expressions/chainedQualifiedExpression.instructions @@ -65,158 +65,158 @@ L0: r(1.0) -> w(inTopLevel|) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) .add(OUT_KEYWORD, inTopLevel) .add(OBJECT_KEYWORD, unresolvedCode) .registerAll()) - mark(registerAll()) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) .add(OUT_KEYWORD, inTopLevel) .add(OBJECT_KEYWORD, unresolvedCode)) - mark(add(OBJECT_KEYWORD, unresolvedCode)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) .add(OUT_KEYWORD, inTopLevel)) - mark(add(OUT_KEYWORD, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel)) - mark(add(IN_KEYWORD, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel)) - mark(add(OVERRIDE_KEYWORD, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel)) - mark(add(PACKAGE_KEYWORD, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel)) - mark(add(IMPORT_KEYWORD, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel)) - mark(add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel)) - mark(add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel)) - mark(add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel)) - mark(add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) mark(BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) - mark(BunchKeywordRegister()) magic(BunchKeywordRegister()) -> + mark(BunchKeywordRegister()) call(BunchKeywordRegister, |) -> r(ABSTRACT_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , ) -> r(FINAL_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , ) -> r(OPEN_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , ) -> r(INTERNAL_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , , ) -> r(PRIVATE_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , , ) -> r(PROTECTED_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , , ) -> r(PUBLIC_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , , ) -> r(CLASS_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , ) -> r(ENUM_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , ) -> r(FUN_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , ) -> r(GET_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , ) -> r(SET_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , ) -> r(TRAIT_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , ) -> r(VAL_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , ) -> r(VAR_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , ) -> r(TYPE_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel)) call(add, add|, , , , ) -> r(IMPORT_KEYWORD) -> r(inTopLevel) -> + mark(add(IMPORT_KEYWORD, inTopLevel)) call(add, add|, , ) -> r(PACKAGE_KEYWORD) -> r(inTopLevel) -> + mark(add(PACKAGE_KEYWORD, inTopLevel)) call(add, add|, , ) -> r(OVERRIDE_KEYWORD) -> r(inTopLevel) -> + mark(add(OVERRIDE_KEYWORD, inTopLevel)) call(add, add|, , ) -> r(IN_KEYWORD) -> r(inTopLevel) -> r(inTopLevel) -> + mark(add(IN_KEYWORD, inTopLevel, inTopLevel)) call(add, add|, , , ) -> r(OUT_KEYWORD) -> r(inTopLevel) -> + mark(add(OUT_KEYWORD, inTopLevel)) call(add, add|, , ) -> r(OBJECT_KEYWORD) -> error(unresolvedCode, No resolved call) magic(unresolvedCode) -> + mark(add(OBJECT_KEYWORD, unresolvedCode)) call(add, add|, , ) -> + mark(registerAll()) call(registerAll, registerAll|) -> L1: 1 NEXT:[] diff --git a/compiler/testData/cfg/expressions/chainedQualifiedExpression.values b/compiler/testData/cfg/expressions/chainedQualifiedExpression.values index 54a5ded8e24..03ec485f499 100644 --- a/compiler/testData/cfg/expressions/chainedQualifiedExpression.values +++ b/compiler/testData/cfg/expressions/chainedQualifiedExpression.values @@ -50,141 +50,141 @@ public open class JetKeywordCompletionContributor() { } } --------------------- -1.0 NEW() -BunchKeywordRegister() NEW() -ABSTRACT_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) COPY -FINAL_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) COPY -OPEN_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) COPY -INTERNAL_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) COPY -PRIVATE_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) COPY -PROTECTED_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) COPY -PUBLIC_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) COPY -CLASS_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) COPY -ENUM_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) COPY -FUN_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) COPY -GET_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) COPY -SET_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) COPY -TRAIT_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) COPY -VAL_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) COPY -VAR_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) COPY -TYPE_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -inTopLevel NEW() -add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) NEW(, , , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) COPY -IMPORT_KEYWORD NEW() -inTopLevel NEW() -add(IMPORT_KEYWORD, inTopLevel) NEW(, , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) COPY -PACKAGE_KEYWORD NEW() -inTopLevel NEW() -add(PACKAGE_KEYWORD, inTopLevel) NEW(, , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) COPY -OVERRIDE_KEYWORD NEW() -inTopLevel NEW() -add(OVERRIDE_KEYWORD, inTopLevel) NEW(, , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) COPY -IN_KEYWORD NEW() -inTopLevel NEW() -inTopLevel NEW() -add(IN_KEYWORD, inTopLevel, inTopLevel) NEW(, , , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) COPY -OUT_KEYWORD NEW() -inTopLevel NEW() -add(OUT_KEYWORD, inTopLevel) NEW(, , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) .add(OUT_KEYWORD, inTopLevel) COPY -OBJECT_KEYWORD NEW() -unresolvedCode NEW() -add(OBJECT_KEYWORD, unresolvedCode) NEW(, , ) -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) .add(OUT_KEYWORD, inTopLevel) .add(OBJECT_KEYWORD, unresolvedCode) COPY -registerAll() NEW() -BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) .add(OUT_KEYWORD, inTopLevel) .add(OBJECT_KEYWORD, unresolvedCode) .registerAll() COPY -{ val inTopLevel = 1.0 BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) .add(OUT_KEYWORD, inTopLevel) .add(OBJECT_KEYWORD, unresolvedCode) .registerAll() } COPY +1.0 : Double NEW() +BunchKeywordRegister() : JetKeywordCompletionContributor.BunchKeywordRegister NEW() +ABSTRACT_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +FINAL_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +OPEN_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +INTERNAL_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +PRIVATE_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +PROTECTED_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +PUBLIC_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +CLASS_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +ENUM_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +FUN_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +GET_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +SET_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +TRAIT_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +VAL_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +VAR_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +TYPE_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +IMPORT_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +add(IMPORT_KEYWORD, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +PACKAGE_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +add(PACKAGE_KEYWORD, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +OVERRIDE_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +add(OVERRIDE_KEYWORD, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +IN_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +inTopLevel : Double NEW() +add(IN_KEYWORD, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +OUT_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +inTopLevel : Double NEW() +add(OUT_KEYWORD, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) .add(OUT_KEYWORD, inTopLevel) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +OBJECT_KEYWORD : {<: [ERROR : Type annotation was missing]} NEW() +unresolvedCode : Double NEW() +add(OBJECT_KEYWORD, unresolvedCode) : JetKeywordCompletionContributor.BunchKeywordRegister NEW(, , ) +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) .add(OUT_KEYWORD, inTopLevel) .add(OBJECT_KEYWORD, unresolvedCode) : JetKeywordCompletionContributor.BunchKeywordRegister COPY +registerAll() : * NEW() +BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) .add(OUT_KEYWORD, inTopLevel) .add(OBJECT_KEYWORD, unresolvedCode) .registerAll() : * COPY +{ val inTopLevel = 1.0 BunchKeywordRegister() .add(ABSTRACT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FINAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(OPEN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(INTERNAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PRIVATE_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PROTECTED_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(PUBLIC_KEYWORD, inTopLevel, inTopLevel, inTopLevel, inTopLevel) .add(CLASS_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(ENUM_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(FUN_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(GET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(SET_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TRAIT_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAL_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(VAR_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(TYPE_KEYWORD, inTopLevel, inTopLevel, inTopLevel) .add(IMPORT_KEYWORD, inTopLevel) .add(PACKAGE_KEYWORD, inTopLevel) .add(OVERRIDE_KEYWORD, inTopLevel) .add(IN_KEYWORD, inTopLevel, inTopLevel) .add(OUT_KEYWORD, inTopLevel) .add(OBJECT_KEYWORD, unresolvedCode) .registerAll() } : * COPY ===================== == ABSTRACT_KEYWORD == val ABSTRACT_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == FINAL_KEYWORD == val FINAL_KEYWORD OPEN_KEYWORD = JetToken() @@ -193,100 +193,100 @@ val FINAL_KEYWORD OPEN_KEYWORD = JetToken() == OPEN_KEYWORD == val OPEN_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == INTERNAL_KEYWORD == val INTERNAL_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == PRIVATE_KEYWORD == val PRIVATE_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == PROTECTED_KEYWORD == val PROTECTED_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == PUBLIC_KEYWORD == val PUBLIC_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == CLASS_KEYWORD == val CLASS_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == ENUM_KEYWORD == val ENUM_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == FUN_KEYWORD == val FUN_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == GET_KEYWORD == val GET_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == SET_KEYWORD == val SET_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == TRAIT_KEYWORD == val TRAIT_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == VAL_KEYWORD == val VAL_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == VAR_KEYWORD == val VAR_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == TYPE_KEYWORD == val TYPE_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == IMPORT_KEYWORD == val IMPORT_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == PACKAGE_KEYWORD == val PACKAGE_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == OVERRIDE_KEYWORD == val OVERRIDE_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == IN_KEYWORD == val IN_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == OUT_KEYWORD == val OUT_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== == OBJECT_KEYWORD == val OBJECT_KEYWORD = JetToken() --------------------- -JetToken() NEW() +JetToken() : JetToken NEW() ===================== diff --git a/compiler/testData/cfg/expressions/expressionAsFunction.instructions b/compiler/testData/cfg/expressions/expressionAsFunction.instructions index 44b62d7531e..b83a5ff8b36 100644 --- a/compiler/testData/cfg/expressions/expressionAsFunction.instructions +++ b/compiler/testData/cfg/expressions/expressionAsFunction.instructions @@ -9,9 +9,9 @@ L0: magic(f: () -> Unit) -> w(f|) 2 mark({ (f)() }) - mark((f)()) mark((f)) r(f) -> + mark((f)()) call((f), invoke|) -> L1: 1 NEXT:[] diff --git a/compiler/testData/cfg/expressions/expressionAsFunction.values b/compiler/testData/cfg/expressions/expressionAsFunction.values index 2d458dfdcc0..52a6534275b 100644 --- a/compiler/testData/cfg/expressions/expressionAsFunction.values +++ b/compiler/testData/cfg/expressions/expressionAsFunction.values @@ -3,8 +3,8 @@ fun invoke(f: () -> Unit) { (f)() } --------------------- -f NEW() -(f) COPY -(f)() NEW() -{ (f)() } COPY +f : {<: () -> Unit} NEW() +(f) : {<: () -> Unit} COPY +(f)() : * NEW() +{ (f)() } : * COPY ===================== diff --git a/compiler/testData/cfg/expressions/incdec.instructions b/compiler/testData/cfg/expressions/incdec.instructions new file mode 100644 index 00000000000..5fa70363fa8 --- /dev/null +++ b/compiler/testData/cfg/expressions/incdec.instructions @@ -0,0 +1,65 @@ +== bar == +fun bar(n: Int) { + +} +--------------------- +L0: + 1 + v(n: Int) + magic(n: Int) -> + w(n|) + 2 mark({ }) + read (Unit) +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== foo == +fun foo() { + var a = 1 + bar(a++) + bar(a--) + bar(++a) + bar(--a) +} +--------------------- +L0: + 1 + 2 mark({ var a = 1 bar(a++) bar(a--) bar(++a) bar(--a) }) + v(var a = 1) + r(1) -> + w(a|) + r(a) -> + mark(a++) + call(++, inc|) -> + w(a|) + mark(bar(a++)) + call(bar, bar|) -> + r(a) -> + mark(a--) + call(--, dec|) -> + w(a|) + mark(bar(a--)) + call(bar, bar|) -> + r(a) -> + mark(++a) + call(++, inc|) -> + w(a|) + mark(bar(++a)) + call(bar, bar|) -> + r(a) -> + mark(--a) + call(--, dec|) -> + w(a|) + mark(bar(--a)) + call(bar, bar|) -> +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== \ No newline at end of file diff --git a/compiler/testData/cfg/expressions/incdec.kt b/compiler/testData/cfg/expressions/incdec.kt new file mode 100644 index 00000000000..55a90b5c61a --- /dev/null +++ b/compiler/testData/cfg/expressions/incdec.kt @@ -0,0 +1,11 @@ +fun bar(n: Int) { + +} + +fun foo() { + var a = 1 + bar(a++) + bar(a--) + bar(++a) + bar(--a) +} \ No newline at end of file diff --git a/compiler/testData/cfg/expressions/incdec.values b/compiler/testData/cfg/expressions/incdec.values new file mode 100644 index 00000000000..060a72f960d --- /dev/null +++ b/compiler/testData/cfg/expressions/incdec.values @@ -0,0 +1,30 @@ +== bar == +fun bar(n: Int) { + +} +--------------------- +===================== +== foo == +fun foo() { + var a = 1 + bar(a++) + bar(a--) + bar(++a) + bar(--a) +} +--------------------- +1 : Int NEW() +a : Int NEW() +a++ : Int COPY +bar(a++) : * NEW() +a : Int NEW() +a-- : Int COPY +bar(a--) : * NEW() +a : Int NEW() +++a : Int NEW() +bar(++a) : * NEW() +a : Int NEW() +--a : Int NEW() +bar(--a) : * NEW() +{ var a = 1 bar(a++) bar(a--) bar(++a) bar(--a) } : * COPY +===================== diff --git a/compiler/testData/cfg/expressions/nothingExpr.instructions b/compiler/testData/cfg/expressions/nothingExpr.instructions index ad4f0bf0576..21a743f846e 100644 --- a/compiler/testData/cfg/expressions/nothingExpr.instructions +++ b/compiler/testData/cfg/expressions/nothingExpr.instructions @@ -38,16 +38,16 @@ L0: 1 2 mark({ null!!.doSomething() bar().doSomething }) mark(null!!.doSomething()) - mark(doSomething()) - mark(null!!) r(null) -> magic(null!!|) -> jmp(error) NEXT:[] +- mark(doSomething()) PREV:[] - call(doSomething, doSomething|) -> PREV:[] - mark(bar().doSomething) PREV:[] - mark(bar()) PREV:[] - call(bar, bar) PREV:[] - jmp(error) NEXT:[] PREV:[] +- mark(doSomething) PREV:[] - call(doSomething, doSomething) -> PREV:[] L1: 1 NEXT:[] PREV:[] diff --git a/compiler/testData/cfg/expressions/nothingExpr.values b/compiler/testData/cfg/expressions/nothingExpr.values index 11eb2496563..4cd3916aecd 100644 --- a/compiler/testData/cfg/expressions/nothingExpr.values +++ b/compiler/testData/cfg/expressions/nothingExpr.values @@ -5,7 +5,7 @@ fun Any?.doSomething() {} == bar == fun bar(): Nothing = throw Exception() --------------------- -Exception() NEW() +Exception() : {<: Throwable} NEW() ===================== == foo == fun foo() { @@ -13,11 +13,11 @@ fun foo() { bar().doSomething } --------------------- -null NEW() -null!! NEW() -doSomething() NEW() -null!!.doSomething() COPY -doSomething NEW() -bar().doSomething COPY -{ null!!.doSomething() bar().doSomething } COPY +null : * NEW() +null!! : * NEW() +doSomething() : * NEW() +null!!.doSomething() : * COPY +doSomething : * NEW() +bar().doSomething : * COPY +{ null!!.doSomething() bar().doSomething } : * COPY ===================== diff --git a/compiler/testData/cfg/expressions/propertySafeCall.values b/compiler/testData/cfg/expressions/propertySafeCall.values index 80da9017c57..a288285f8f4 100644 --- a/compiler/testData/cfg/expressions/propertySafeCall.values +++ b/compiler/testData/cfg/expressions/propertySafeCall.values @@ -3,8 +3,8 @@ fun test(s: String?) { s?.length } --------------------- -s NEW() -length NEW() -s?.length COPY -{ s?.length } COPY +s : {<: CharSequence?} NEW() +length : * NEW() +s?.length : * COPY +{ s?.length } : * COPY ===================== diff --git a/compiler/testData/cfg/expressions/qualifiedExpressionWithoutSelector.values b/compiler/testData/cfg/expressions/qualifiedExpressionWithoutSelector.values index 8ac8e57cef1..71888c1db6a 100644 --- a/compiler/testData/cfg/expressions/qualifiedExpressionWithoutSelector.values +++ b/compiler/testData/cfg/expressions/qualifiedExpressionWithoutSelector.values @@ -3,7 +3,7 @@ fun foo(s: String) { s. } --------------------- -s NEW() -s. NEW() -{ s. } COPY +s : * NEW() +s. : * NEW() +{ s. } : * COPY ===================== diff --git a/compiler/testData/cfg/expressions/thisExpression.values b/compiler/testData/cfg/expressions/thisExpression.values index 36c7359fc2e..a1db0a07d38 100644 --- a/compiler/testData/cfg/expressions/thisExpression.values +++ b/compiler/testData/cfg/expressions/thisExpression.values @@ -3,6 +3,6 @@ fun Function0.foo() { this() } --------------------- -this() NEW() -{ this() } COPY +this() : * NEW() +{ this() } : * COPY ===================== diff --git a/compiler/testData/cfg/expressions/unresolvedCall.instructions b/compiler/testData/cfg/expressions/unresolvedCall.instructions index 9bf196dff93..3bfc2044c02 100644 --- a/compiler/testData/cfg/expressions/unresolvedCall.instructions +++ b/compiler/testData/cfg/expressions/unresolvedCall.instructions @@ -10,10 +10,10 @@ L0: w(a|) 2 mark({ a.foo() }) mark(a.foo()) - mark(foo()) error(foo, No resolved call) error(foo, No resolved call) r(a) -> + mark(foo()) magic(foo()|) -> L1: 1 NEXT:[] diff --git a/compiler/testData/cfg/expressions/unresolvedCall.values b/compiler/testData/cfg/expressions/unresolvedCall.values index 54739cc2bc7..e7c190cc644 100644 --- a/compiler/testData/cfg/expressions/unresolvedCall.values +++ b/compiler/testData/cfg/expressions/unresolvedCall.values @@ -3,8 +3,8 @@ fun test(a: Any) { a.foo() } --------------------- -a NEW() -foo() NEW() -a.foo() COPY -{ a.foo() } COPY +a : * NEW() +foo() : * NEW() +a.foo() : * COPY +{ a.foo() } : * COPY ===================== diff --git a/compiler/testData/cfg/expressions/unresolvedProperty.values b/compiler/testData/cfg/expressions/unresolvedProperty.values index 242d96f7738..a9903e08e05 100644 --- a/compiler/testData/cfg/expressions/unresolvedProperty.values +++ b/compiler/testData/cfg/expressions/unresolvedProperty.values @@ -3,8 +3,8 @@ fun test(a: Any) { a.foo } --------------------- -a NEW() -foo NEW() -a.foo COPY -{ a.foo } COPY +a : * NEW() +foo : * NEW() +a.foo : * COPY +{ a.foo } : * COPY ===================== diff --git a/compiler/testData/cfg/expressions/unusedExpressionSimpleName.values b/compiler/testData/cfg/expressions/unusedExpressionSimpleName.values index 21c1d285846..6e60c264f8f 100644 --- a/compiler/testData/cfg/expressions/unusedExpressionSimpleName.values +++ b/compiler/testData/cfg/expressions/unusedExpressionSimpleName.values @@ -3,6 +3,6 @@ fun main(arg : Array) { a } --------------------- -a NEW() -{ a } COPY +a : * NEW() +{ a } : * COPY ===================== diff --git a/compiler/testData/cfg/functions/DefaultValuesForArguments.instructions b/compiler/testData/cfg/functions/DefaultValuesForArguments.instructions new file mode 100644 index 00000000000..c7177b5ce53 --- /dev/null +++ b/compiler/testData/cfg/functions/DefaultValuesForArguments.instructions @@ -0,0 +1,26 @@ +== foo == +fun foo(i: Int = 1, j: Int) = i + j +--------------------- +L0: + 1 + v(i: Int = 1) + jmp?(L2 [after default value for parameter i]) NEXT:[magic(i: Int = 1) -> , r(1) -> ] + r(1) -> +L2 [after default value for parameter i]: + magic(i: Int = 1) -> PREV:[jmp?(L2 [after default value for parameter i]), r(1) -> ] + merge(i: Int = 1|, ) -> + w(i|) + v(j: Int) + magic(j: Int) -> + w(j|) + r(i) -> + r(j) -> + mark(i + j) + call(+, plus|, ) -> +L1: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== diff --git a/compiler/testData/cfg/functions/DefaultValuesForArguments.kt b/compiler/testData/cfg/functions/DefaultValuesForArguments.kt new file mode 100644 index 00000000000..29b4d4e0d46 --- /dev/null +++ b/compiler/testData/cfg/functions/DefaultValuesForArguments.kt @@ -0,0 +1 @@ +fun foo(i: Int = 1, j: Int) = i + j \ No newline at end of file diff --git a/compiler/testData/cfg/functions/DefaultValuesForArguments.values b/compiler/testData/cfg/functions/DefaultValuesForArguments.values new file mode 100644 index 00000000000..1f17659350c --- /dev/null +++ b/compiler/testData/cfg/functions/DefaultValuesForArguments.values @@ -0,0 +1,9 @@ +== foo == +fun foo(i: Int = 1, j: Int) = i + j +--------------------- +1 : Int NEW() +i: Int = 1 : Int NEW(, ) +i : Int NEW() +j : Int NEW() +i + j : Int NEW(, ) +===================== diff --git a/compiler/testData/cfg/tailCalls/finally.values b/compiler/testData/cfg/tailCalls/finally.values index 3c892f5ed05..164bdd47631 100644 --- a/compiler/testData/cfg/tailCalls/finally.values +++ b/compiler/testData/cfg/tailCalls/finally.values @@ -7,6 +7,6 @@ tailRecursive fun test() : Int { } } --------------------- -test() NEW() -{ test() } COPY +test() : * NEW() +{ test() } : * COPY ===================== diff --git a/compiler/testData/cfg/tailCalls/finallyWithReturn.values b/compiler/testData/cfg/tailCalls/finallyWithReturn.values index ae6a6469285..11c80464648 100644 --- a/compiler/testData/cfg/tailCalls/finallyWithReturn.values +++ b/compiler/testData/cfg/tailCalls/finallyWithReturn.values @@ -7,5 +7,5 @@ tailRecursive fun test() : Int { } } --------------------- -test() NEW() +test() : Int NEW() ===================== diff --git a/compiler/testData/cfg/tailCalls/sum.instructions b/compiler/testData/cfg/tailCalls/sum.instructions index 80567d12824..ce457b14d51 100644 --- a/compiler/testData/cfg/tailCalls/sum.instructions +++ b/compiler/testData/cfg/tailCalls/sum.instructions @@ -14,29 +14,29 @@ L0: w(sum|) 2 mark({ if (x == 0.toLong()) return sum return sum(x - 1, sum + x) }) mark(if (x == 0.toLong()) return sum) - mark(x == 0.toLong()) r(x) -> mark(0.toLong()) - mark(toLong()) r(0) -> + mark(toLong()) call(toLong, toLong|) -> + mark(x == 0.toLong()) call(==, equals|, ) -> jf(L2|) NEXT:[read (Unit), r(sum) -> ] r(sum) -> ret(*|) L1 NEXT:[] -- jmp(L3) NEXT:[mark(sum(x - 1, sum + x))] PREV:[] +- jmp(L3) NEXT:[r(x) -> ] PREV:[] L2: read (Unit) PREV:[jf(L2|)] L3: - mark(sum(x - 1, sum + x)) - mark(x - 1) r(x) -> r(1) -> + mark(x - 1) call(-, minus|, ) -> - mark(sum + x) r(sum) -> r(x) -> + mark(sum + x) call(+, plus|, ) -> + mark(sum(x - 1, sum + x)) call(sum, sum|, ) -> ret(*|) L1 L1: diff --git a/compiler/testData/cfg/tailCalls/sum.values b/compiler/testData/cfg/tailCalls/sum.values index 89681b86d73..7df26749973 100644 --- a/compiler/testData/cfg/tailCalls/sum.values +++ b/compiler/testData/cfg/tailCalls/sum.values @@ -4,17 +4,17 @@ tailRecursive fun sum(x: Long, sum: Long): Long { return sum(x - 1, sum + x) } --------------------- -x NEW() -0 NEW() -toLong() NEW() -0.toLong() COPY -x == 0.toLong() NEW(, ) -sum NEW() -x NEW() -1 NEW() -x - 1 NEW(, ) -sum NEW() -x NEW() -sum + x NEW(, ) -sum(x - 1, sum + x) NEW(, ) +x : OR{{<: Any}, {<: Any}} NEW() +0 : {<: Number} NEW() +toLong() : {<: Any?} NEW() +0.toLong() : {<: Any?} COPY +x == 0.toLong() : Boolean NEW(, ) +sum : Long NEW() +x : Long NEW() +1 : Int NEW() +x - 1 : Long NEW(, ) +sum : Long NEW() +x : Long NEW() +sum + x : Long NEW(, ) +sum(x - 1, sum + x) : Long NEW(, ) ===================== diff --git a/compiler/testData/cfg/tailCalls/try.values b/compiler/testData/cfg/tailCalls/try.values index 8605d77c651..269ddaa7c86 100644 --- a/compiler/testData/cfg/tailCalls/try.values +++ b/compiler/testData/cfg/tailCalls/try.values @@ -7,5 +7,5 @@ tailRecursive fun foo() { } } --------------------- -foo() NEW() +foo() : Unit NEW() ===================== diff --git a/compiler/testData/cfg/tailCalls/tryCatchFinally.values b/compiler/testData/cfg/tailCalls/tryCatchFinally.values index e555ef8ad11..08302009127 100644 --- a/compiler/testData/cfg/tailCalls/tryCatchFinally.values +++ b/compiler/testData/cfg/tailCalls/tryCatchFinally.values @@ -9,12 +9,12 @@ fun test() : Unit { } } --------------------- -test() NEW() -{ test() } COPY -test() NEW() -{ test() } COPY -test() NEW() -{ test() } COPY -try { test() } catch (any : Exception) { test() } finally { test() } NEW(, ) -{ try { test() } catch (any : Exception) { test() } finally { test() } } COPY +test() : * NEW() +{ test() } : * COPY +test() : * NEW() +{ test() } : * COPY +test() : * NEW() +{ test() } : * COPY +try { test() } catch (any : Exception) { test() } finally { test() } : * NEW(, ) +{ try { test() } catch (any : Exception) { test() } finally { test() } } : * COPY ===================== diff --git a/compiler/testData/checkLocalVariablesTable/catchClause.kt b/compiler/testData/checkLocalVariablesTable/catchClause.kt new file mode 100644 index 00000000000..0c76d23638a --- /dev/null +++ b/compiler/testData/checkLocalVariablesTable/catchClause.kt @@ -0,0 +1,15 @@ +class A { + fun foo() { + try { + val a = 1 + } + catch(e : Throwable) { + + } + } +} + +// METHOD : A.foo()V +// VARIABLE : NAME=a TYPE=I INDEX=1 +// VARIABLE : NAME=e TYPE=Ljava/lang/Throwable; INDEX=1 +// VARIABLE : NAME=this TYPE=LA; INDEX=0 diff --git a/compiler/testData/compileKotlinAgainstKotlin/InlinedConstants.A.kt b/compiler/testData/compileKotlinAgainstKotlin/InlinedConstants.A.kt new file mode 100644 index 00000000000..6e624ae137e --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/InlinedConstants.A.kt @@ -0,0 +1,18 @@ +package constants + +import java.lang.annotation.Retention +import java.lang.annotation.RetentionPolicy + +public val b: Byte = 100 +public val s: Short = 20000 +public val i: Int = 2000000 +public val l: Long = 2000000000000L +public val f: Float = 3.14f +public val d: Double = 3.14 +public val bb: Boolean = true +public val c: Char = '\u03c0' // pi symbol + +public val str: String = ":)" + +[Retention(RetentionPolicy.RUNTIME)] +public annotation class AnnotationClass(public val value: String) \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstKotlin/InlinedConstants.B.kt b/compiler/testData/compileKotlinAgainstKotlin/InlinedConstants.B.kt new file mode 100644 index 00000000000..4c341b87225 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/InlinedConstants.B.kt @@ -0,0 +1,12 @@ +import constants.* + +AnnotationClass("$b $s $i $l $f $d $bb $c $str") +class DummyClass() + +fun main(args: Array) { + val klass = javaClass()!! + val annotationClass = javaClass() + val annotation = klass.getAnnotation(annotationClass)!! + val value = annotation.value + require(value == "100 20000 2000000 2000000000000 3.14 3.14 true \u03c0 :)", "Annotation value: $value") +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/FunctionReturnTypes.kt b/compiler/testData/diagnostics/tests/FunctionReturnTypes.kt index a73b71e57f2..d4e0fbdcfcc 100644 --- a/compiler/testData/diagnostics/tests/FunctionReturnTypes.kt +++ b/compiler/testData/diagnostics/tests/FunctionReturnTypes.kt @@ -1,3 +1,5 @@ +// !DIAGNOSTICS: -UNREACHABLE_CODE + fun none() {} fun unitEmptyInfer() {} @@ -51,7 +53,7 @@ fun blockAndAndMismatch1() : Int { return true && false } fun blockAndAndMismatch2() : Int { - (return true) && (return false) + (return true) && (return false) } fun blockAndAndMismatch3() : Int { @@ -61,7 +63,7 @@ fun blockAndAndMismatch4() : Int { return true || false } fun blockAndAndMismatch5() : Int { - (return true) || (return false) + (return true) || (return false) } fun blockReturnValueTypeMatch1() : Int { return if (1 > 2) 1.0 else 2.0 diff --git a/compiler/testData/diagnostics/tests/LValueAssignment.kt b/compiler/testData/diagnostics/tests/LValueAssignment.kt index b048163c50c..dd41b22982e 100644 --- a/compiler/testData/diagnostics/tests/LValueAssignment.kt +++ b/compiler/testData/diagnostics/tests/LValueAssignment.kt @@ -134,7 +134,7 @@ class Test() { (a : Array)[4]++ (ab.getArray() : Array)[54] += 43 - this[54] = 34 + this[54] = 34 } } diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/commasAndWhitespaces.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/commasAndWhitespaces.kt new file mode 100644 index 00000000000..a32de3a361c --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/commasAndWhitespaces.kt @@ -0,0 +1,12 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun testCommasAndWhitespaces() { + fun bar(i: Int, s: String, x: Any) {} + + bar( 1 , todo() , "" ) +} + +fun todo() = throw Exception() + + + diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/commentsInDeadCode.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/commentsInDeadCode.kt new file mode 100644 index 00000000000..7640277569f --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/commentsInDeadCode.kt @@ -0,0 +1,22 @@ +package a + +fun test1() { + bar( + 11, + todo(),//comment1 + ""//comment2 + ) +} + +fun test2() { + bar(11, todo()/*comment1*/, ""/*comment2*/) +} +fun test3() { + bar(11, @l(todo()/*comment*/), "") +} + +fun todo() = throw Exception() + +fun bar(i: Int, s: String, a: Any) {} + + diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCallInInvokeCall.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCallInInvokeCall.kt new file mode 100644 index 00000000000..9285b7122f1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCallInInvokeCall.kt @@ -0,0 +1,11 @@ +fun testInvoke() { + fun Nothing.invoke() = this + todo()() +} + +fun testInvokeWithLambda() { + fun Nothing.invoke(i: Int, f: () -> Int) = f + todo()(1){ 42 } +} + +fun todo() = throw Exception() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCallInReceiver.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCallInReceiver.kt new file mode 100644 index 00000000000..bce9404313e --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCallInReceiver.kt @@ -0,0 +1,11 @@ +fun test11() { + fun Any.bar(i: Int) {} + todo().bar(1) +} + +fun test12() { + fun Any.bar(i: Int) {} + todo()?.bar(1) +} + +fun todo() = throw Exception() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/UnreachableCode.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeDifferentExamples.kt similarity index 82% rename from compiler/testData/diagnostics/tests/UnreachableCode.kt rename to compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeDifferentExamples.kt index e79c920e843..d3019a67a22 100644 --- a/compiler/testData/diagnostics/tests/UnreachableCode.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeDifferentExamples.kt @@ -1,3 +1,4 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION fun t1() : Int{ return 0 @@ -46,7 +47,7 @@ fun t3() : Any { 1 } -fun t4(a : Boolean) : Int { +fun t4(a : Boolean) : Int { do { return 1 } @@ -54,7 +55,7 @@ fun t4(a : Boolean) : Int { 1 } -fun t4break(a : Boolean) : Int { +fun t4break(a : Boolean) : Int { do { break } @@ -109,7 +110,7 @@ fun t7() : Int { 2 } catch (e : Any) { - 2 + 2 } return 1 // this is OK, like in Java } @@ -127,25 +128,25 @@ fun t8() : Int { } fun blockAndAndMismatch() : Boolean { - (return true) || (return false) + (return true) || (return false) return true } fun tf() : Int { - try {return 1} finally{return 1} + try {return 1} finally{return 1} return 1 } -fun failtest(a : Int) : Int { - if (fail() || true) { +fun failtest(a : Int) : Int { + if (fail() || true) { } return 1 } fun foo(a : Nothing) : Unit { - 1 - a + 1 + a 2 } @@ -161,7 +162,7 @@ fun nullIsNotNothing() : Unit { fail() } -fun returnInWhile(a: Int) { +fun returnInWhile(a: Int) { do {return} while (1 > a) } diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/DeadCode.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeFromDifferentSources.kt similarity index 78% rename from compiler/testData/diagnostics/tests/controlFlowAnalysis/DeadCode.kt rename to compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeFromDifferentSources.kt index 0cd3fb77b75..63c2571b0ca 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/DeadCode.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeFromDifferentSources.kt @@ -1,7 +1,7 @@ package c fun test1() { - val r: Nothing = null!! + val r: Nothing = null!! } fun test2(a: A) { diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInArrayAccess.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInArrayAccess.kt new file mode 100644 index 00000000000..b9109c096c9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInArrayAccess.kt @@ -0,0 +1,40 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun testArrayAccess1(array: Array) { + array[todo()] +} + +fun testArrayAccess2() { + fun Nothing.get(i: Int, s: String) {} + todo()[1, ""] +} + +fun testAraryAccess3() { + fun Nothing.get(n: Nothing) {} + todo()[todo()] +} + +fun testArrayAssignment1(array: Array) { + array[todo()] = 11 +} + +fun testArrayAssignment2(array: Array) { + array[1] = todo() +} + +fun testArrayAssignment3(n: Nothing) { + fun Nothing.set(i: Int, j: Int) {} + n[1] = 2 +} + +fun testArrayAssignment4(n: Nothing) { + fun Nothing.set(i: Int, a: Any) {} + n[1] = todo() +} + +fun testArrayPlusAssign(array: Array) { + fun Any.plusAssign(a: Any) {} + array[1] += todo() +} + +fun todo() = throw Exception() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInAssignment.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInAssignment.kt new file mode 100644 index 00000000000..85e9e23aaf0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInAssignment.kt @@ -0,0 +1,18 @@ +fun testAssignment() { + var a = 1 + a = todo() +} + +fun testVariableDeclaration() { + val a = todo() +} + +fun testPlusAssign() { + fun Int.plusAssign(i: Int) {} + + var a = 1 + a += todo() +} + + +fun todo() = throw Exception() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInBinaryExpressions.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInBinaryExpressions.kt new file mode 100644 index 00000000000..42b4727af76 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInBinaryExpressions.kt @@ -0,0 +1,39 @@ +fun testBinary1() { + fun Int.times(s: String) {} + + todo() * "" +} +fun testBinary2() { + "1" + todo() +} + +fun testElvis1() { + todo() ?: "" +} + +fun testElvis2(s: String?) { + s ?: todo() + + bar() +} + +fun testAnd1(b: Boolean) { + b && todo() + + bar() +} + +fun testAnd2(b: Boolean) { + todo() && b +} + +fun returnInBinary1(): Boolean { + (return true) && (return false) +} + +fun returnInBinary2(): Boolean { + (return true) || (return false) +} + +fun todo() = throw Exception() +fun bar() {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInCalls.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInCalls.kt new file mode 100644 index 00000000000..6bc59d6867a --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInCalls.kt @@ -0,0 +1,13 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun testArgumentInCall() { + fun bar(i: Int, s: String, x: Any) {} + + bar(1, todo(), "") +} + +fun testArgumentInVariableAsFunctionCall(f: (Any) -> Unit) { + f(todo()) +} + +fun todo() = throw Exception() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInDeadCode.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInDeadCode.kt new file mode 100644 index 00000000000..53001d49508 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInDeadCode.kt @@ -0,0 +1,24 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun unreachable0() { + return + return todo() +} + +fun unreachable2() { + return + val a = todo() +} + +fun unreachable3() { + return + bar(todo()) +} + +fun unreachable4(array: Array) { + return + array[todo()] +} + +fun bar(a: Any) {} +fun todo() = throw Exception() diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInIf.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInIf.kt new file mode 100644 index 00000000000..283281aecc3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInIf.kt @@ -0,0 +1,12 @@ +fun testIf() { + if (todo()) 1 else 2 +} + +fun testIf1(b: Boolean) { + if (b) todo() else 1 + + bar() +} + +fun todo() = throw Exception() +fun bar() {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInInnerExpressions.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInInnerExpressions.kt new file mode 100644 index 00000000000..16f1395f857 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInInnerExpressions.kt @@ -0,0 +1,13 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun testCompound() { + fun Nothing.get(i: Int) {} + todo()!![12] +} + +fun testCompound1() { + fun Int.times(s: String): Array = throw Exception() + (todo() * "")[1] +} + +fun todo() = throw Exception() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInLocalDeclarations.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInLocalDeclarations.kt new file mode 100644 index 00000000000..db437307072 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInLocalDeclarations.kt @@ -0,0 +1,36 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun testObject() { + object : Foo(todo()) { + fun foo() = 1 + } +} + +fun testObjectExpression() { + val a = object : Foo(todo()) { + fun foo() = 1 + } +} + +fun testObjectExpression1() { + fun bar(i: Int, x: Any) {} + + bar(1, object : Foo(todo()) { + fun foo() = 1 + }) +} + +fun testClassDeclaration() { + class C : Foo(todo()) {} + + bar() +} + +fun testFunctionDefaultArgument() { + fun foo(x: Int = todo()) { bar() } +} + +open class Foo(i: Int) {} + +fun todo() = throw Exception() +fun bar() {} diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInLoops.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInLoops.kt new file mode 100644 index 00000000000..f5f85117c8c --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInLoops.kt @@ -0,0 +1,21 @@ +fun testFor() { + fun Nothing.iterator() = (0..1).iterator() + + for (i in todo()) {} +} + +fun testWhile() { + while (todo()) { + } +} + +fun testDoWhile() { + do { + + } while(todo()) + + bar() +} + +fun todo() = throw Exception() +fun bar() {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInReturn.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInReturn.kt new file mode 100644 index 00000000000..d8574db97a2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInReturn.kt @@ -0,0 +1,5 @@ +fun testReturn() { + return todo() +} + +fun todo() = throw Exception() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInUnaryExpr.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInUnaryExpr.kt new file mode 100644 index 00000000000..1d158e012d2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInUnaryExpr.kt @@ -0,0 +1,15 @@ +fun testPrefix() { + fun Any.not() {} + !todo() +} + +fun testPostfixWithCall(n: Nothing) { + fun Nothing.inc(): Nothing = this + n++ +} + +fun testPostfixSpecial() { + todo()!! +} + +fun todo() = throw Exception() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unreachableCode.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInWhileFromBreak.kt similarity index 68% rename from compiler/testData/diagnostics/tests/controlFlowAnalysis/unreachableCode.kt rename to compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInWhileFromBreak.kt index 431865396f2..978ee032ac0 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/unreachableCode.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInWhileFromBreak.kt @@ -3,20 +3,20 @@ fun bar(a: Any, b: Any) {} fun test(arr: Array) { while (true) { - foo(break) + foo(break) } while (true) { - bar(arr, break) + bar(arr, break) } while (true) { - arr[break] + arr[break] } while (true) { - arr[1] = break + arr[1] = break } while (true) { @@ -32,7 +32,7 @@ fun test(arr: Array) { while (true) { var x = 1 - x = break + x = break } // TODO: bug, should be fixed in CFA @@ -50,6 +50,6 @@ fun test(arr: Array) { } while (true) { - break ?: null + break ?: null } } diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2585_1.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt2585_1.kt similarity index 80% rename from compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2585_1.kt rename to compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt2585_1.kt index 185066d307b..2bd2e6bd6c6 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2585_1.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt2585_1.kt @@ -2,7 +2,7 @@ fun foo(x: String): String { try { - throw RuntimeException() + throw RuntimeException() } finally { try { } catch (e: Exception) { diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2585_2.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt2585_2.kt similarity index 88% rename from compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2585_2.kt rename to compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt2585_2.kt index 8b6d9f6ed9a..638e2fe6759 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2585_2.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt2585_2.kt @@ -2,7 +2,7 @@ fun foo() { try { - throw RuntimeException() + throw RuntimeException() } catch (e: Exception) { return // <- Wrong UNREACHABLE_CODE } finally { diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2585_3.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt2585_3.kt similarity index 78% rename from compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2585_3.kt rename to compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt2585_3.kt index f2f917ceda4..b2b68a84a96 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2585_3.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt2585_3.kt @@ -2,7 +2,7 @@ fun foo(x: String): String { try { - throw RuntimeException() //should be marked as unreachable, but is not + throw RuntimeException() //should be marked as unreachable, but is not } finally { throw NullPointerException() } diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt3162tryAsInitializer.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt3162tryAsInitializer.kt new file mode 100644 index 00000000000..a459cf6cf91 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt3162tryAsInitializer.kt @@ -0,0 +1,12 @@ +//KT-3162 More precise try-finally error marking + +fun foo(x: String) : String { + val a = try { + x + } finally { + try { + } catch (e: Exception) { + } + return x + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt5200DeadCodeInLambdas.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt5200DeadCodeInLambdas.kt new file mode 100644 index 00000000000..0d53ea4e81a --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt5200DeadCodeInLambdas.kt @@ -0,0 +1,27 @@ +//KT-5200 Mark unreachable code in lambdas + +fun test1(): String { + doCall @local { + () : String -> + throw NullPointerException() + "b3" //unmarked + } + + return "OK" +} + +fun test2(nonLocal: String, b: Boolean): String { + doCall @local { + () : String -> + if (b) { + return@local "b1" + } else { + return@local "b2" + } + "b3" //unmarked + } + + return nonLocal +} + +inline fun doCall(block: ()-> String) = block() diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2334.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2334.kt new file mode 100644 index 00000000000..4801d17d73f --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2334.kt @@ -0,0 +1,5 @@ +//KT-2334 An error 'local function without body' is not reported + +fun foo() { + fun bar() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.kt b/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.kt index 7f5528485b6..0b4e3efab96 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.kt @@ -1,3 +1,4 @@ +// !DIAGNOSTICS: -UNREACHABLE_CODE package kt770_351_735 @@ -120,9 +121,9 @@ fun testStatementInExpressionContext() { val a1: Unit = z = 334 val f = for (i in 1..10) {} if (true) return z = 34 - return while (true) {} + return while (true) {} } fun testStatementInExpressionContext2() { - val a2: Unit = while(true) {} + val a2: Unit = while(true) {} } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlStructures/tryReturnType.kt b/compiler/testData/diagnostics/tests/controlStructures/tryReturnType.kt index a61bf21605b..58f53253516 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/tryReturnType.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/tryReturnType.kt @@ -5,7 +5,7 @@ fun foo() : Int { doSmth() } catch (e: Exception) { - return "" + return "" } finally { return "" diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/kt5155WhenBranches.kt b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/kt5155WhenBranches.kt new file mode 100644 index 00000000000..0f4799b9755 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/kt5155WhenBranches.kt @@ -0,0 +1,14 @@ +//KT-5155 Auto-casts do not work with when + +fun foo(s: String?) { + when { + s == null -> 1 + s.foo() -> 2 + else -> 3 + } +} + +fun String.foo() = true + + + diff --git a/compiler/testData/diagnostics/tests/incompleteCode/checkNothingIsSubtype.kt b/compiler/testData/diagnostics/tests/incompleteCode/checkNothingIsSubtype.kt index 8eee69ddae7..a4510fc8b5d 100644 --- a/compiler/testData/diagnostics/tests/incompleteCode/checkNothingIsSubtype.kt +++ b/compiler/testData/diagnostics/tests/incompleteCode/checkNothingIsSubtype.kt @@ -9,6 +9,6 @@ fun test(nothing: Nothing?) { } fun sum(a : IntArray) : Int { - for (n - return "?" -} \ No newline at end of file +for (n +return "?" +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/incompleteWhen.kt b/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/incompleteWhen.kt index d76fd7427d0..e169c711d74 100644 --- a/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/incompleteWhen.kt +++ b/compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/incompleteWhen.kt @@ -1,3 +1,3 @@ fun test(a: Any) { when (a) -} \ No newline at end of file +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt2445.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt2445.kt index 34eb3099f80..2f9e0da3fab 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt2445.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt2445.kt @@ -1,3 +1,4 @@ +// !DIAGNOSTICS: -UNREACHABLE_CODE //KT-2445 Calling method with function with generic parameter causes compile-time exception package a @@ -7,4 +8,4 @@ fun main(args: Array) { } } -fun test(callback: (R) -> Unit):Unit = callback(null!!) \ No newline at end of file +fun test(callback: (R) -> Unit):Unit = callback(null!!) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt2838.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt2838.kt index 33518f5f228..23ff0757a4b 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt2838.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt2838.kt @@ -1,3 +1,4 @@ +// !DIAGNOSTICS: -UNREACHABLE_CODE //KT-2838 Type inference failed on passing null as a nullable argument package a @@ -9,9 +10,9 @@ fun test(a: Int) { bar(a, null) } fun test1(a: Int) { - foo(a, throw Exception()) + foo(a, throw Exception()) } fun test2(a: Int) { - bar(a, throw Exception()) + bar(a, throw Exception()) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/regressions/kt411.kt b/compiler/testData/diagnostics/tests/regressions/kt411.kt index 3c6ee7ef2a5..2f5c43386f5 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt411.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt411.kt @@ -37,7 +37,7 @@ fun t3() : String { else { return 2 } - return@l 0 + return@l 0 } ) invoker( diff --git a/compiler/testData/diagnostics/tests/regressions/kt58.kt b/compiler/testData/diagnostics/tests/regressions/kt58.kt index 665fa7ad48e..9ed3897e281 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt58.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt58.kt @@ -17,7 +17,7 @@ fun lock(lock : Lock, body : () -> T) : T { //more tests fun t1() : Int { try { - return 1 + return 1 } finally { return 2 diff --git a/compiler/testData/loadJava/compiledKotlin/prop/Constants.kt b/compiler/testData/loadJava/compiledKotlin/prop/Constants.kt new file mode 100644 index 00000000000..935c1a68f5b --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/prop/Constants.kt @@ -0,0 +1,17 @@ +//ALLOW_AST_ACCESS +package test + +val b: Byte = 100 +val b1: Byte = 1 +val s: Short = 20000 +val s1: Short = 1 +val i: Int = 2000000 +val i1: Short = 1 +val l: Long = 2000000000000L +val l1: Long = 1 +val f: Float = 3.14f +val d: Double = 3.14 +val bb: Boolean = true +val c: Char = '\u03c0' // pi symbol + +val str: String = ":)" \ No newline at end of file diff --git a/compiler/testData/loadJava/compiledKotlin/prop/Constants.txt b/compiler/testData/loadJava/compiledKotlin/prop/Constants.txt new file mode 100644 index 00000000000..d465db083c5 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/prop/Constants.txt @@ -0,0 +1,28 @@ +package test + +internal val b: kotlin.Byte = 100.toByte() + internal fun (): kotlin.Byte +internal val b1: kotlin.Byte = 1.toByte() + internal fun (): kotlin.Byte +internal val bb: kotlin.Boolean = true + internal fun (): kotlin.Boolean +internal val c: kotlin.Char = #960(Ï€) + internal fun (): kotlin.Char +internal val d: kotlin.Double = 3.14.toDouble() + internal fun (): kotlin.Double +internal val f: kotlin.Float = 3.14.toFloat() + internal fun (): kotlin.Float +internal val i: kotlin.Int = 2000000 + internal fun (): kotlin.Int +internal val i1: kotlin.Short = 1.toShort() + internal fun (): kotlin.Short +internal val l: kotlin.Long = 2000000000000.toLong() + internal fun (): kotlin.Long +internal val l1: kotlin.Long = 1.toLong() + internal fun (): kotlin.Long +internal val s: kotlin.Short = 20000.toShort() + internal fun (): kotlin.Short +internal val s1: kotlin.Short = 1.toShort() + internal fun (): kotlin.Short +internal val str: kotlin.String = ":)" + internal fun (): kotlin.String \ No newline at end of file diff --git a/compiler/testData/psi/ForWithMultiDecl.txt b/compiler/testData/psi/ForWithMultiDecl.txt index 72b4094e80e..50fce4d50bf 100644 --- a/compiler/testData/psi/ForWithMultiDecl.txt +++ b/compiler/testData/psi/ForWithMultiDecl.txt @@ -658,17 +658,9 @@ JetFile: ForWithMultiDecl.kt PsiErrorElement:Expecting 'in' PsiWhiteSpace(' ') - LOOP_RANGE - FUNCTION_LITERAL_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - BLOCK - - PsiElement(RBRACE)('}') - PsiErrorElement:Expecting ')' - - PsiWhiteSpace('\n') BODY - PsiErrorElement:Expecting an expression - + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/DoWhileWithEmptyCondition.kt b/compiler/testData/psi/recovery/DoWhileWithEmptyCondition.kt new file mode 100644 index 00000000000..b069f62ae2c --- /dev/null +++ b/compiler/testData/psi/recovery/DoWhileWithEmptyCondition.kt @@ -0,0 +1,7 @@ +fun test(): Boolean { + do { + + } while() + + return true +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/DoWhileWithEmptyCondition.txt b/compiler/testData/psi/recovery/DoWhileWithEmptyCondition.txt new file mode 100644 index 00000000000..93f2df38e04 --- /dev/null +++ b/compiler/testData/psi/recovery/DoWhileWithEmptyCondition.txt @@ -0,0 +1,43 @@ +JetFile: DoWhileWithEmptyCondition.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Boolean') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + DO_WHILE + PsiElement(do)('do') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + PsiElement(while)('while') + PsiElement(LPAR)('(') + CONDITION + PsiErrorElement:Expecting an expression + + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n ') + RETURN + PsiElement(return)('return') + PsiWhiteSpace(' ') + BOOLEAN_CONSTANT + PsiElement(true)('true') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/DoWhileWithoutLPar.kt b/compiler/testData/psi/recovery/DoWhileWithoutLPar.kt new file mode 100644 index 00000000000..3305b371633 --- /dev/null +++ b/compiler/testData/psi/recovery/DoWhileWithoutLPar.kt @@ -0,0 +1,7 @@ +fun test(): Boolean { + do { + + } while + + return true +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/DoWhileWithoutLPar.txt b/compiler/testData/psi/recovery/DoWhileWithoutLPar.txt new file mode 100644 index 00000000000..7f9b850ddd0 --- /dev/null +++ b/compiler/testData/psi/recovery/DoWhileWithoutLPar.txt @@ -0,0 +1,40 @@ +JetFile: DoWhileWithoutLPar.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Boolean') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + DO_WHILE + PsiElement(do)('do') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + PsiElement(while)('while') + PsiErrorElement:Expecting a condition in parentheses '(...)' + + PsiWhiteSpace('\n\n ') + RETURN + PsiElement(return)('return') + PsiWhiteSpace(' ') + BOOLEAN_CONSTANT + PsiElement(true)('true') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForEmptyParentheses.kt b/compiler/testData/psi/recovery/ForEmptyParentheses.kt new file mode 100644 index 00000000000..d650562110c --- /dev/null +++ b/compiler/testData/psi/recovery/ForEmptyParentheses.kt @@ -0,0 +1,7 @@ +fun test(): Int { + for () { + + } + + return 1 +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForEmptyParentheses.txt b/compiler/testData/psi/recovery/ForEmptyParentheses.txt new file mode 100644 index 00000000000..54637bcd5c6 --- /dev/null +++ b/compiler/testData/psi/recovery/ForEmptyParentheses.txt @@ -0,0 +1,41 @@ +JetFile: ForEmptyParentheses.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + PsiErrorElement:Expecting a variable name + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + RETURN + PsiElement(return)('return') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForEmptyWithoutBody.kt b/compiler/testData/psi/recovery/ForEmptyWithoutBody.kt new file mode 100644 index 00000000000..ee39105562d --- /dev/null +++ b/compiler/testData/psi/recovery/ForEmptyWithoutBody.kt @@ -0,0 +1,5 @@ +fun test(): Int { + for () + + return 1 +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForEmptyWithoutBody.txt b/compiler/testData/psi/recovery/ForEmptyWithoutBody.txt new file mode 100644 index 00000000000..a2fb1b359e0 --- /dev/null +++ b/compiler/testData/psi/recovery/ForEmptyWithoutBody.txt @@ -0,0 +1,36 @@ +JetFile: ForEmptyWithoutBody.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + PsiErrorElement:Expecting a variable name + + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n ') + BODY + RETURN + PsiElement(return)('return') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForNoBodyBeforeRBrace.kt b/compiler/testData/psi/recovery/ForNoBodyBeforeRBrace.kt new file mode 100644 index 00000000000..6bea4afc769 --- /dev/null +++ b/compiler/testData/psi/recovery/ForNoBodyBeforeRBrace.kt @@ -0,0 +1,5 @@ +fun test() { + while (true) { + for () + } +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForNoBodyBeforeRBrace.txt b/compiler/testData/psi/recovery/ForNoBodyBeforeRBrace.txt new file mode 100644 index 00000000000..47a3fe600de --- /dev/null +++ b/compiler/testData/psi/recovery/ForNoBodyBeforeRBrace.txt @@ -0,0 +1,41 @@ +JetFile: ForNoBodyBeforeRBrace.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + WHILE + PsiElement(while)('while') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + BOOLEAN_CONSTANT + PsiElement(true)('true') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + PsiErrorElement:Expecting a variable name + + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + BODY + PsiErrorElement:Expecting an expression + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForWithOnlyOneLParInEOF.kt b/compiler/testData/psi/recovery/ForWithOnlyOneLParInEOF.kt new file mode 100644 index 00000000000..f27c0d2aa4b --- /dev/null +++ b/compiler/testData/psi/recovery/ForWithOnlyOneLParInEOF.kt @@ -0,0 +1 @@ +fun test() = for ( \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForWithOnlyOneLParInEOF.txt b/compiler/testData/psi/recovery/ForWithOnlyOneLParInEOF.txt new file mode 100644 index 00000000000..f64c5e36c16 --- /dev/null +++ b/compiler/testData/psi/recovery/ForWithOnlyOneLParInEOF.txt @@ -0,0 +1,26 @@ +JetFile: ForWithOnlyOneLParInEOF.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiErrorElement:Expecting a variable name + + PsiErrorElement:Expecting 'in' + + PsiErrorElement:Expecting ')' + + BODY + \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForWithoutBodyInEOF.kt b/compiler/testData/psi/recovery/ForWithoutBodyInEOF.kt new file mode 100644 index 00000000000..9d6b05d33bf --- /dev/null +++ b/compiler/testData/psi/recovery/ForWithoutBodyInEOF.kt @@ -0,0 +1 @@ +fun test() = for () \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForWithoutBodyInEOF.txt b/compiler/testData/psi/recovery/ForWithoutBodyInEOF.txt new file mode 100644 index 00000000000..8fcf670047c --- /dev/null +++ b/compiler/testData/psi/recovery/ForWithoutBodyInEOF.txt @@ -0,0 +1,23 @@ +JetFile: ForWithoutBodyInEOF.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + PsiErrorElement:Expecting a variable name + + PsiElement(RPAR)(')') + BODY + PsiErrorElement:Expecting an expression + \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForWithoutLPar.kt b/compiler/testData/psi/recovery/ForWithoutLPar.kt new file mode 100644 index 00000000000..bae4369a47e --- /dev/null +++ b/compiler/testData/psi/recovery/ForWithoutLPar.kt @@ -0,0 +1,5 @@ +fun test(): Int { + for + + return 1 +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForWithoutLPar.txt b/compiler/testData/psi/recovery/ForWithoutLPar.txt new file mode 100644 index 00000000000..b7db1cf5028 --- /dev/null +++ b/compiler/testData/psi/recovery/ForWithoutLPar.txt @@ -0,0 +1,33 @@ +JetFile: ForWithoutLPar.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiErrorElement:Expecting '(' to open a loop range + + PsiWhiteSpace('\n\n ') + BODY + RETURN + PsiElement(return)('return') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForWithoutLParInEOF.kt b/compiler/testData/psi/recovery/ForWithoutLParInEOF.kt new file mode 100644 index 00000000000..297c47865fa --- /dev/null +++ b/compiler/testData/psi/recovery/ForWithoutLParInEOF.kt @@ -0,0 +1 @@ +fun test() = for \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForWithoutLParInEOF.txt b/compiler/testData/psi/recovery/ForWithoutLParInEOF.txt new file mode 100644 index 00000000000..b5bb46c5dff --- /dev/null +++ b/compiler/testData/psi/recovery/ForWithoutLParInEOF.txt @@ -0,0 +1,20 @@ +JetFile: ForWithoutLParInEOF.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + FOR + PsiElement(for)('for') + PsiErrorElement:Expecting '(' to open a loop range + + BODY + PsiErrorElement:Expecting an expression + \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForWithoutParamButWithRange.kt b/compiler/testData/psi/recovery/ForWithoutParamButWithRange.kt new file mode 100644 index 00000000000..ace3d6f7f84 --- /dev/null +++ b/compiler/testData/psi/recovery/ForWithoutParamButWithRange.kt @@ -0,0 +1,4 @@ +fun test() { + for (in some()) { + } +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForWithoutParamButWithRange.txt b/compiler/testData/psi/recovery/ForWithoutParamButWithRange.txt new file mode 100644 index 00000000000..e62d99b1c18 --- /dev/null +++ b/compiler/testData/psi/recovery/ForWithoutParamButWithRange.txt @@ -0,0 +1,39 @@ +JetFile: ForWithoutParamButWithRange.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiErrorElement:Expecting a variable name + + PsiElement(in)('in') + PsiWhiteSpace(' ') + LOOP_RANGE + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('some') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BODY + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForWithoutRange.kt b/compiler/testData/psi/recovery/ForWithoutRange.kt new file mode 100644 index 00000000000..9cbd45e8906 --- /dev/null +++ b/compiler/testData/psi/recovery/ForWithoutRange.kt @@ -0,0 +1,5 @@ +fun test() { + for (some) + + bar() +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/ForWithoutRange.txt b/compiler/testData/psi/recovery/ForWithoutRange.txt new file mode 100644 index 00000000000..078249feef5 --- /dev/null +++ b/compiler/testData/psi/recovery/ForWithoutRange.txt @@ -0,0 +1,33 @@ +JetFile: ForWithoutRange.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('some') + PsiErrorElement:Expecting 'in' + + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n ') + BODY + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/IfWithEmptyCondition.kt b/compiler/testData/psi/recovery/IfWithEmptyCondition.kt new file mode 100644 index 00000000000..31b7744a998 --- /dev/null +++ b/compiler/testData/psi/recovery/IfWithEmptyCondition.kt @@ -0,0 +1,5 @@ +fun test() { + if () + + return true +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/IfWithEmptyCondition.txt b/compiler/testData/psi/recovery/IfWithEmptyCondition.txt new file mode 100644 index 00000000000..0387edc8c4e --- /dev/null +++ b/compiler/testData/psi/recovery/IfWithEmptyCondition.txt @@ -0,0 +1,31 @@ +JetFile: IfWithEmptyCondition.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + IF + PsiElement(if)('if') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + PsiErrorElement:Expecting an expression + + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n ') + THEN + RETURN + PsiElement(return)('return') + PsiWhiteSpace(' ') + BOOLEAN_CONSTANT + PsiElement(true)('true') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/IfWithoutLPar.kt b/compiler/testData/psi/recovery/IfWithoutLPar.kt new file mode 100644 index 00000000000..afeb4d035fd --- /dev/null +++ b/compiler/testData/psi/recovery/IfWithoutLPar.kt @@ -0,0 +1,6 @@ +fun test() { + if + + if (other) { + } +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/IfWithoutLPar.txt b/compiler/testData/psi/recovery/IfWithoutLPar.txt new file mode 100644 index 00000000000..7b11eff9b59 --- /dev/null +++ b/compiler/testData/psi/recovery/IfWithoutLPar.txt @@ -0,0 +1,36 @@ +JetFile: IfWithoutLPar.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + IF + PsiElement(if)('if') + PsiErrorElement:Expecting a condition in parentheses '(...)' + + PsiWhiteSpace('\n\n ') + THEN + IF + PsiElement(if)('if') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('other') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + THEN + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/WhenWithoutBraces.kt b/compiler/testData/psi/recovery/WhenWithoutBraces.kt new file mode 100644 index 00000000000..02fa66a9393 --- /dev/null +++ b/compiler/testData/psi/recovery/WhenWithoutBraces.kt @@ -0,0 +1,5 @@ +fun test() { + when + + bar() +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/WhenWithoutBraces.txt b/compiler/testData/psi/recovery/WhenWithoutBraces.txt new file mode 100644 index 00000000000..c6f02f30cfa --- /dev/null +++ b/compiler/testData/psi/recovery/WhenWithoutBraces.txt @@ -0,0 +1,27 @@ +JetFile: WhenWithoutBraces.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + WHEN + PsiElement(when)('when') + PsiErrorElement:Expecting '{' + + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/WhileWithEmptyCondition.kt b/compiler/testData/psi/recovery/WhileWithEmptyCondition.kt new file mode 100644 index 00000000000..fb0debc6a2a --- /dev/null +++ b/compiler/testData/psi/recovery/WhileWithEmptyCondition.kt @@ -0,0 +1,5 @@ +fun test() { + while () + + return +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/WhileWithEmptyCondition.txt b/compiler/testData/psi/recovery/WhileWithEmptyCondition.txt new file mode 100644 index 00000000000..5db6abf0700 --- /dev/null +++ b/compiler/testData/psi/recovery/WhileWithEmptyCondition.txt @@ -0,0 +1,28 @@ +JetFile: WhileWithEmptyCondition.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + WHILE + PsiElement(while)('while') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + PsiErrorElement:Expecting an expression + + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n ') + BODY + RETURN + PsiElement(return)('return') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/WhileWithoutLPar.kt b/compiler/testData/psi/recovery/WhileWithoutLPar.kt new file mode 100644 index 00000000000..0803ed1226c --- /dev/null +++ b/compiler/testData/psi/recovery/WhileWithoutLPar.kt @@ -0,0 +1,5 @@ +fun test(): Boolean { + while + + return true +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/WhileWithoutLPar.txt b/compiler/testData/psi/recovery/WhileWithoutLPar.txt new file mode 100644 index 00000000000..64606ef4b66 --- /dev/null +++ b/compiler/testData/psi/recovery/WhileWithoutLPar.txt @@ -0,0 +1,33 @@ +JetFile: WhileWithoutLPar.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Boolean') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + WHILE + PsiElement(while)('while') + PsiErrorElement:Expecting a condition in parentheses '(...)' + + PsiWhiteSpace('\n\n ') + BODY + RETURN + PsiElement(return)('return') + PsiWhiteSpace(' ') + BOOLEAN_CONSTANT + PsiElement(true)('true') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/WithWithoutInAndMultideclaration.kt b/compiler/testData/psi/recovery/WithWithoutInAndMultideclaration.kt new file mode 100644 index 00000000000..6f010e85fcb --- /dev/null +++ b/compiler/testData/psi/recovery/WithWithoutInAndMultideclaration.kt @@ -0,0 +1,5 @@ +fun test() { + for ((i, j)) + + foo() +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/WithWithoutInAndMultideclaration.txt b/compiler/testData/psi/recovery/WithWithoutInAndMultideclaration.txt new file mode 100644 index 00000000000..2125b2e4d26 --- /dev/null +++ b/compiler/testData/psi/recovery/WithWithoutInAndMultideclaration.txt @@ -0,0 +1,40 @@ +JetFile: WithWithoutInAndMultideclaration.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('test') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + FOR + PsiElement(for)('for') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION + PsiElement(LPAR)('(') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('i') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + MULTI_VARIABLE_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('j') + PsiElement(RPAR)(')') + PsiErrorElement:Expecting 'in' + + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n ') + BODY + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('foo') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/asJava/KotlinLightClassTestGenerated.java b/compiler/tests/org/jetbrains/jet/asJava/KotlinLightClassTestGenerated.java index 2ce4a5ad997..ffc688593f2 100644 --- a/compiler/tests/org/jetbrains/jet/asJava/KotlinLightClassTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/asJava/KotlinLightClassTestGenerated.java @@ -86,6 +86,21 @@ public class KotlinLightClassTestGenerated extends AbstractKotlinLightClassTest doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Generic.kt"); } + @TestMetadata("IntOverridesAny.kt") + public void testIntOverridesAny() throws Exception { + doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.kt"); + } + + @TestMetadata("NullableUnitReturn.kt") + public void testNullableUnitReturn() throws Exception { + doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.kt"); + } + + @TestMetadata("OverrideAnyWithUnit.kt") + public void testOverrideAnyWithUnit() throws Exception { + doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.kt"); + } + @TestMetadata("Primitives.kt") public void testPrimitives() throws Exception { doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Primitives.kt"); @@ -116,6 +131,21 @@ public class KotlinLightClassTestGenerated extends AbstractKotlinLightClassTest doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/TraitClassObjectField.kt"); } + @TestMetadata("UnitAsGenericArgument.kt") + public void testUnitAsGenericArgument() throws Exception { + doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.kt"); + } + + @TestMetadata("UnitParameter.kt") + public void testUnitParameter() throws Exception { + doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.kt"); + } + + @TestMetadata("VoidReturn.kt") + public void testVoidReturn() throws Exception { + doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.kt"); + } + @TestMetadata("_DefaultPackage.kt") public void test_DefaultPackage() throws Exception { doTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/_DefaultPackage.kt"); diff --git a/compiler/tests/org/jetbrains/jet/cfg/AbstractControlFlowTest.java b/compiler/tests/org/jetbrains/jet/cfg/AbstractControlFlowTest.java index 64a552fb074..569662b8224 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/AbstractControlFlowTest.java +++ b/compiler/tests/org/jetbrains/jet/cfg/AbstractControlFlowTest.java @@ -19,9 +19,9 @@ package org.jetbrains.jet.cfg; import kotlin.Function3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl; import org.jetbrains.jet.lang.cfg.pseudocode.instructions.Instruction; import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionImpl; -import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl; import org.jetbrains.jet.lang.resolve.BindingContext; import java.util.*; @@ -34,7 +34,7 @@ public abstract class AbstractControlFlowTest extends AbstractPseudocodeTest { @NotNull StringBuilder out, @NotNull BindingContext bindingContext ) { - final int nextInstructionsColumnWidth = countNextInstructionsColumnWidth(pseudocode.getAllInstructions()); + final int nextInstructionsColumnWidth = countNextInstructionsColumnWidth(pseudocode.getInstructionsIncludingDeadCode()); dumpInstructions(pseudocode, out, new Function3() { @Override @@ -107,9 +107,9 @@ public abstract class AbstractControlFlowTest extends AbstractPseudocodeTest { @Override protected void checkPseudocode(PseudocodeImpl pseudocode) { //check edges directions - Collection instructions = pseudocode.getAllInstructions(); + Collection instructions = pseudocode.getInstructionsIncludingDeadCode(); for (Instruction instruction : instructions) { - if (!((InstructionImpl)instruction).getDead()) { + if (!((InstructionImpl)instruction).getMarkedAsDead()) { for (Instruction nextInstruction : instruction.getNextInstructions()) { assertTrue("instruction '" + instruction + "' has '" + nextInstruction + "' among next instructions list, but not vice versa", nextInstruction.getPreviousInstructions().contains(instruction)); diff --git a/compiler/tests/org/jetbrains/jet/cfg/AbstractDataFlowTest.java b/compiler/tests/org/jetbrains/jet/cfg/AbstractDataFlowTest.java index 64b095a31ed..27b37d7a209 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/AbstractDataFlowTest.java +++ b/compiler/tests/org/jetbrains/jet/cfg/AbstractDataFlowTest.java @@ -49,7 +49,7 @@ public abstract class AbstractDataFlowTest extends AbstractPseudocodeTest { pseudocodeVariablesData.getVariableUseStatusData(); final String initPrefix = " INIT:"; final String usePrefix = " USE:"; - final int initializersColumnWidth = countDataColumnWidth(initPrefix, pseudocode.getAllInstructions(), variableInitializers); + final int initializersColumnWidth = countDataColumnWidth(initPrefix, pseudocode.getInstructionsIncludingDeadCode(), variableInitializers); dumpInstructions(pseudocode, out, new Function3() { @Override diff --git a/compiler/tests/org/jetbrains/jet/cfg/AbstractPseudoValueTest.kt b/compiler/tests/org/jetbrains/jet/cfg/AbstractPseudoValueTest.kt index f795983e262..f980f195c5b 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/AbstractPseudoValueTest.kt +++ b/compiler/tests/org/jetbrains/jet/cfg/AbstractPseudoValueTest.kt @@ -22,9 +22,15 @@ import org.jetbrains.jet.lang.psi.JetElement import org.jetbrains.jet.lang.psi.JetTreeVisitorVoid import org.jetbrains.jet.lang.resolve.BindingContext import java.util.* +import org.jetbrains.jet.lang.cfg.pseudocode.collectValueUsages +import org.jetbrains.jet.lang.cfg.pseudocode.TypePredicate +import org.jetbrains.jet.lang.cfg.pseudocode.getExpectedTypePredicate public abstract class AbstractPseudoValueTest : AbstractPseudocodeTest() { override fun dumpInstructions(pseudocode: PseudocodeImpl, out: StringBuilder, bindingContext: BindingContext) { + val valueUsageMap = pseudocode.collectValueUsages() + val expectedTypePredicateMap = HashMap() + fun getElementToValueMap(pseudocode: PseudocodeImpl): Map { val elementToValues = LinkedHashMap() pseudocode.getCorrespondingElement().accept(object : JetTreeVisitorVoid() { @@ -44,6 +50,11 @@ public abstract class AbstractPseudoValueTest : AbstractPseudocodeTest() { fun elementText(element: JetElement): String = element.getText()!!.replaceAll("\\s+", " ") + fun valueDecl(value: PseudoValue): String { + val typePredicate = expectedTypePredicateMap.getOrPut(value) { getExpectedTypePredicate(value, valueUsageMap, bindingContext) } + return "${value.debugName}: $typePredicate" + } + fun valueDescription(element: JetElement, value: PseudoValue): String { return if (value.element != element) "COPY" else "NEW${value.createdAt.inputValues.makeString(", ", "(", ")")}" } @@ -52,14 +63,14 @@ public abstract class AbstractPseudoValueTest : AbstractPseudocodeTest() { if (elementToValues.isEmpty()) return val elementColumnWidth = elementToValues.keySet().map { elementText(it).length() }.max()!! - val valueColumnWidth = elementToValues.values().map { it.debugName.length() }.max()!! + val valueColumnWidth = elementToValues.values().map { valueDecl(it).length() }.max()!! val valueDescColumnWidth = elementToValues.entrySet().map { valueDescription(it.key, it.value).length }.max()!! for ((element, value) in elementToValues.entrySet()) { out .append("%1$-${elementColumnWidth}s".format(elementText(element))) .append(" ") - .append("%1$-${valueColumnWidth}s".format(value.debugName)) + .append("%1$-${valueColumnWidth}s".format(valueDecl(value))) .append(" ") .append("%1$-${valueDescColumnWidth}s".format(valueDescription(element, value))) .append("\n") diff --git a/compiler/tests/org/jetbrains/jet/cfg/AbstractPseudocodeTest.java b/compiler/tests/org/jetbrains/jet/cfg/AbstractPseudocodeTest.java index 1d8315db966..734e4c4d512 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/AbstractPseudocodeTest.java +++ b/compiler/tests/org/jetbrains/jet/cfg/AbstractPseudocodeTest.java @@ -140,7 +140,7 @@ public abstract class AbstractPseudocodeTest extends KotlinTestWithEnvironment { @NotNull Set remainedAfterPostProcessInstructions ) { boolean isRemovedThroughPostProcess = !remainedAfterPostProcessInstructions.contains(instruction); - assert isRemovedThroughPostProcess == ((InstructionImpl)instruction).getDead(); + assert isRemovedThroughPostProcess == ((InstructionImpl)instruction).getMarkedAsDead(); return isRemovedThroughPostProcess ? "-" : " "; } @@ -179,7 +179,7 @@ public abstract class AbstractPseudocodeTest extends KotlinTestWithEnvironment { @NotNull StringBuilder out, @NotNull Function3 getInstructionData ) { - List instructions = pseudocode.getAllInstructions(); + List instructions = pseudocode.getInstructionsIncludingDeadCode(); Set remainedAfterPostProcessInstructions = Sets.newHashSet(pseudocode.getInstructions()); List labels = pseudocode.getLabels(); int instructionColumnWidth = countInstructionColumnWidth(instructions); diff --git a/compiler/tests/org/jetbrains/jet/cfg/CFGraphToDotFilePrinter.java b/compiler/tests/org/jetbrains/jet/cfg/CFGraphToDotFilePrinter.java index 4dc51c2b970..878996e3845 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/CFGraphToDotFilePrinter.java +++ b/compiler/tests/org/jetbrains/jet/cfg/CFGraphToDotFilePrinter.java @@ -44,7 +44,7 @@ public class CFGraphToDotFilePrinter { int[] count = new int[1]; Map nodeToName = new HashMap(); for (Pseudocode pseudocode : pseudocodes) { - dumpNodes(((PseudocodeImpl)pseudocode).getAllInstructions(), out, count, nodeToName, Sets + dumpNodes(pseudocode.getInstructionsIncludingDeadCode(), out, count, nodeToName, Sets .newHashSet(pseudocode.getInstructions())); } int i = 0; @@ -61,7 +61,7 @@ public class CFGraphToDotFilePrinter { out.println("subgraph cluster_" + i + " {\n" + "label=\"" + label + "\";\n" + "color=blue;\n"); - dumpEdges(((PseudocodeImpl)pseudocode).getAllInstructions(), out, count, nodeToName); + dumpEdges(pseudocode.getInstructionsIncludingDeadCode(), out, count, nodeToName); out.println("}"); i++; } @@ -76,7 +76,7 @@ public class CFGraphToDotFilePrinter { public void visitLocalFunctionDeclarationInstruction(LocalFunctionDeclarationInstruction instruction) { int index = count[0]; // instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";", nodeToName); - printEdge(out, nodeToName.get(instruction), nodeToName.get(((PseudocodeImpl)instruction.getBody()).getAllInstructions().get(0)), null); + printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getBody().getInstructionsIncludingDeadCode().get(0)), null); visitInstructionWithNext(instruction); } diff --git a/compiler/tests/org/jetbrains/jet/cfg/ControlFlowTestGenerated.java b/compiler/tests/org/jetbrains/jet/cfg/ControlFlowTestGenerated.java index 5d9e7198df8..b4f0f972387 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/ControlFlowTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/cfg/ControlFlowTestGenerated.java @@ -31,7 +31,7 @@ import org.jetbrains.jet.cfg.AbstractControlFlowTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("compiler/testData/cfg") -@InnerTestClasses({ControlFlowTestGenerated.Arrays.class, ControlFlowTestGenerated.Basic.class, ControlFlowTestGenerated.Bugs.class, ControlFlowTestGenerated.ControlStructures.class, ControlFlowTestGenerated.Conventions.class, ControlFlowTestGenerated.DeadCode.class, ControlFlowTestGenerated.Declarations.class, ControlFlowTestGenerated.Expressions.class, ControlFlowTestGenerated.TailCalls.class}) +@InnerTestClasses({ControlFlowTestGenerated.Arrays.class, ControlFlowTestGenerated.Basic.class, ControlFlowTestGenerated.Bugs.class, ControlFlowTestGenerated.ControlStructures.class, ControlFlowTestGenerated.Conventions.class, ControlFlowTestGenerated.DeadCode.class, ControlFlowTestGenerated.Declarations.class, ControlFlowTestGenerated.Expressions.class, ControlFlowTestGenerated.Functions.class, ControlFlowTestGenerated.TailCalls.class}) public class ControlFlowTestGenerated extends AbstractControlFlowTest { public void testAllFilesPresentInCfg() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/cfg"), Pattern.compile("^(.+)\\.kt$"), true); @@ -155,6 +155,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/cfg/conventions"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("bothReceivers.kt") + public void testBothReceivers() throws Exception { + doTest("compiler/testData/cfg/conventions/bothReceivers.kt"); + } + @TestMetadata("equals.kt") public void testEquals() throws Exception { doTest("compiler/testData/cfg/conventions/equals.kt"); @@ -359,6 +364,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest { doTest("compiler/testData/cfg/expressions/expressionAsFunction.kt"); } + @TestMetadata("incdec.kt") + public void testIncdec() throws Exception { + doTest("compiler/testData/cfg/expressions/incdec.kt"); + } + @TestMetadata("LazyBooleans.kt") public void testLazyBooleans() throws Exception { doTest("compiler/testData/cfg/expressions/LazyBooleans.kt"); @@ -406,6 +416,19 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest { } + @TestMetadata("compiler/testData/cfg/functions") + public static class Functions extends AbstractControlFlowTest { + public void testAllFilesPresentInFunctions() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/cfg/functions"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("DefaultValuesForArguments.kt") + public void testDefaultValuesForArguments() throws Exception { + doTest("compiler/testData/cfg/functions/DefaultValuesForArguments.kt"); + } + + } + @TestMetadata("compiler/testData/cfg/tailCalls") public static class TailCalls extends AbstractControlFlowTest { public void testAllFilesPresentInTailCalls() throws Exception { @@ -450,6 +473,7 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest { suite.addTestSuite(DeadCode.class); suite.addTest(Declarations.innerSuite()); suite.addTestSuite(Expressions.class); + suite.addTestSuite(Functions.class); suite.addTestSuite(TailCalls.class); return suite; } diff --git a/compiler/tests/org/jetbrains/jet/cfg/PseudoValueTestGenerated.java b/compiler/tests/org/jetbrains/jet/cfg/PseudoValueTestGenerated.java index cbe2296d004..f530d7e7c02 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/PseudoValueTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/cfg/PseudoValueTestGenerated.java @@ -33,7 +33,7 @@ import org.jetbrains.jet.cfg.AbstractPseudoValueTest; @InnerTestClasses({PseudoValueTestGenerated.Cfg.class, PseudoValueTestGenerated.Cfg_variables.class}) public class PseudoValueTestGenerated extends AbstractPseudoValueTest { @TestMetadata("compiler/testData/cfg") - @InnerTestClasses({Cfg.Arrays.class, Cfg.Basic.class, Cfg.Bugs.class, Cfg.ControlStructures.class, Cfg.Conventions.class, Cfg.DeadCode.class, Cfg.Declarations.class, Cfg.Expressions.class, Cfg.TailCalls.class}) + @InnerTestClasses({Cfg.Arrays.class, Cfg.Basic.class, Cfg.Bugs.class, Cfg.ControlStructures.class, Cfg.Conventions.class, Cfg.DeadCode.class, Cfg.Declarations.class, Cfg.Expressions.class, Cfg.Functions.class, Cfg.TailCalls.class}) public static class Cfg extends AbstractPseudoValueTest { public void testAllFilesPresentInCfg() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/cfg"), Pattern.compile("^(.+)\\.kt$"), true); @@ -157,6 +157,11 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/cfg/conventions"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("bothReceivers.kt") + public void testBothReceivers() throws Exception { + doTest("compiler/testData/cfg/conventions/bothReceivers.kt"); + } + @TestMetadata("equals.kt") public void testEquals() throws Exception { doTest("compiler/testData/cfg/conventions/equals.kt"); @@ -361,6 +366,11 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest { doTest("compiler/testData/cfg/expressions/expressionAsFunction.kt"); } + @TestMetadata("incdec.kt") + public void testIncdec() throws Exception { + doTest("compiler/testData/cfg/expressions/incdec.kt"); + } + @TestMetadata("LazyBooleans.kt") public void testLazyBooleans() throws Exception { doTest("compiler/testData/cfg/expressions/LazyBooleans.kt"); @@ -408,6 +418,19 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest { } + @TestMetadata("compiler/testData/cfg/functions") + public static class Functions extends AbstractPseudoValueTest { + public void testAllFilesPresentInFunctions() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/cfg/functions"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("DefaultValuesForArguments.kt") + public void testDefaultValuesForArguments() throws Exception { + doTest("compiler/testData/cfg/functions/DefaultValuesForArguments.kt"); + } + + } + @TestMetadata("compiler/testData/cfg/tailCalls") public static class TailCalls extends AbstractPseudoValueTest { public void testAllFilesPresentInTailCalls() throws Exception { @@ -452,6 +475,7 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest { suite.addTestSuite(DeadCode.class); suite.addTest(Declarations.innerSuite()); suite.addTestSuite(Expressions.class); + suite.addTestSuite(Functions.class); suite.addTestSuite(TailCalls.class); return suite; } diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 8d9b77441ed..c5b4ea4326f 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -469,11 +469,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/UnitValue.kt"); } - @TestMetadata("UnreachableCode.kt") - public void testUnreachableCode() throws Exception { - doTest("compiler/testData/diagnostics/tests/UnreachableCode.kt"); - } - @TestMetadata("Unresolved.kt") public void testUnresolved() throws Exception { doTest("compiler/testData/diagnostics/tests/Unresolved.kt"); @@ -1239,7 +1234,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { } @TestMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis") - @InnerTestClasses({ControlFlowAnalysis.DefiniteReturn.class}) + @InnerTestClasses({ControlFlowAnalysis.DeadCode.class, ControlFlowAnalysis.DefiniteReturn.class}) public static class ControlFlowAnalysis extends AbstractJetDiagnosticsTest { public void testAllFilesPresentInControlFlowAnalysis() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/diagnostics/tests/controlFlowAnalysis"), Pattern.compile("^(.+)\\.kt$"), true); @@ -1260,11 +1255,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/checkPropertyAccessor.kt"); } - @TestMetadata("DeadCode.kt") - public void testDeadCode() throws Exception { - doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/DeadCode.kt"); - } - @TestMetadata("definiteReturnInWhen.kt") public void testDefiniteReturnInWhen() throws Exception { doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturnInWhen.kt"); @@ -1335,26 +1325,16 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2330.kt"); } + @TestMetadata("kt2334.kt") + public void testKt2334() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2334.kt"); + } + @TestMetadata("kt2369.kt") public void testKt2369() throws Exception { doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2369.kt"); } - @TestMetadata("kt2585_1.kt") - public void testKt2585_1() throws Exception { - doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2585_1.kt"); - } - - @TestMetadata("kt2585_2.kt") - public void testKt2585_2() throws Exception { - doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2585_2.kt"); - } - - @TestMetadata("kt2585_3.kt") - public void testKt2585_3() throws Exception { - doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2585_3.kt"); - } - @TestMetadata("kt2845.kt") public void testKt2845() throws Exception { doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt2845.kt"); @@ -1455,16 +1435,134 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/UninitializedOrReassignedVariables.kt"); } - @TestMetadata("unreachableCode.kt") - public void testUnreachableCode() throws Exception { - doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/unreachableCode.kt"); - } - @TestMetadata("varInitializationInIfInCycle.kt") public void testVarInitializationInIfInCycle() throws Exception { doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/varInitializationInIfInCycle.kt"); } + @TestMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode") + public static class DeadCode extends AbstractJetDiagnosticsTest { + public void testAllFilesPresentInDeadCode() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("commasAndWhitespaces.kt") + public void testCommasAndWhitespaces() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/commasAndWhitespaces.kt"); + } + + @TestMetadata("commentsInDeadCode.kt") + public void testCommentsInDeadCode() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/commentsInDeadCode.kt"); + } + + @TestMetadata("deadCallInInvokeCall.kt") + public void testDeadCallInInvokeCall() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCallInInvokeCall.kt"); + } + + @TestMetadata("deadCallInReceiver.kt") + public void testDeadCallInReceiver() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCallInReceiver.kt"); + } + + @TestMetadata("deadCodeDifferentExamples.kt") + public void testDeadCodeDifferentExamples() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeDifferentExamples.kt"); + } + + @TestMetadata("deadCodeFromDifferentSources.kt") + public void testDeadCodeFromDifferentSources() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeFromDifferentSources.kt"); + } + + @TestMetadata("deadCodeInArrayAccess.kt") + public void testDeadCodeInArrayAccess() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInArrayAccess.kt"); + } + + @TestMetadata("deadCodeInAssignment.kt") + public void testDeadCodeInAssignment() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInAssignment.kt"); + } + + @TestMetadata("deadCodeInBinaryExpressions.kt") + public void testDeadCodeInBinaryExpressions() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInBinaryExpressions.kt"); + } + + @TestMetadata("deadCodeInCalls.kt") + public void testDeadCodeInCalls() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInCalls.kt"); + } + + @TestMetadata("deadCodeInDeadCode.kt") + public void testDeadCodeInDeadCode() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInDeadCode.kt"); + } + + @TestMetadata("deadCodeInIf.kt") + public void testDeadCodeInIf() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInIf.kt"); + } + + @TestMetadata("deadCodeInInnerExpressions.kt") + public void testDeadCodeInInnerExpressions() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInInnerExpressions.kt"); + } + + @TestMetadata("deadCodeInLocalDeclarations.kt") + public void testDeadCodeInLocalDeclarations() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInLocalDeclarations.kt"); + } + + @TestMetadata("deadCodeInLoops.kt") + public void testDeadCodeInLoops() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInLoops.kt"); + } + + @TestMetadata("deadCodeInReturn.kt") + public void testDeadCodeInReturn() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInReturn.kt"); + } + + @TestMetadata("deadCodeInUnaryExpr.kt") + public void testDeadCodeInUnaryExpr() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInUnaryExpr.kt"); + } + + @TestMetadata("deadCodeInWhileFromBreak.kt") + public void testDeadCodeInWhileFromBreak() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/deadCodeInWhileFromBreak.kt"); + } + + @TestMetadata("kt2585_1.kt") + public void testKt2585_1() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt2585_1.kt"); + } + + @TestMetadata("kt2585_2.kt") + public void testKt2585_2() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt2585_2.kt"); + } + + @TestMetadata("kt2585_3.kt") + public void testKt2585_3() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt2585_3.kt"); + } + + @TestMetadata("kt3162tryAsInitializer.kt") + public void testKt3162tryAsInitializer() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt3162tryAsInitializer.kt"); + } + + @TestMetadata("kt5200DeadCodeInLambdas.kt") + public void testKt5200DeadCodeInLambdas() throws Exception { + doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/kt5200DeadCodeInLambdas.kt"); + } + + } + @TestMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/definiteReturn") public static class DefiniteReturn extends AbstractJetDiagnosticsTest { public void testAllFilesPresentInDefiniteReturn() throws Exception { @@ -1491,6 +1589,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { public static Test innerSuite() { TestSuite suite = new TestSuite("ControlFlowAnalysis"); suite.addTestSuite(ControlFlowAnalysis.class); + suite.addTestSuite(DeadCode.class); suite.addTestSuite(DefiniteReturn.class); return suite; } @@ -2019,6 +2118,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/dataFlowInfoTraversal/kt4332WhenBranches.kt"); } + @TestMetadata("kt5155WhenBranches.kt") + public void testKt5155WhenBranches() throws Exception { + doTest("compiler/testData/diagnostics/tests/dataFlowInfoTraversal/kt5155WhenBranches.kt"); + } + @TestMetadata("kt5182WhenBranches.kt") public void testKt5182WhenBranches() throws Exception { doTest("compiler/testData/diagnostics/tests/dataFlowInfoTraversal/kt5182WhenBranches.kt"); diff --git a/compiler/tests/org/jetbrains/jet/codegen/CheckLocalVariablesTableTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/CheckLocalVariablesTableTestGenerated.java index dbbbb0b758f..79c77dbeeec 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/CheckLocalVariablesTableTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/CheckLocalVariablesTableTestGenerated.java @@ -36,6 +36,11 @@ public class CheckLocalVariablesTableTestGenerated extends AbstractCheckLocalVar JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/checkLocalVariablesTable"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("catchClause.kt") + public void testCatchClause() throws Exception { + doTest("compiler/testData/checkLocalVariablesTable/catchClause.kt"); + } + @TestMetadata("copyFunction.kt") public void testCopyFunction() throws Exception { doTest("compiler/testData/checkLocalVariablesTable/copyFunction.kt"); diff --git a/compiler/tests/org/jetbrains/jet/codegen/forTestCompile/ForTestCompileSomething.java b/compiler/tests/org/jetbrains/jet/codegen/forTestCompile/ForTestCompileSomething.java index 43a68af5c38..2dbf60693e0 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/forTestCompile/ForTestCompileSomething.java +++ b/compiler/tests/org/jetbrains/jet/codegen/forTestCompile/ForTestCompileSomething.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.codegen.forTestCompile; import com.google.common.io.Files; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.TimeUtils; @@ -27,14 +28,12 @@ import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import com.intellij.util.containers.Stack; - import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; abstract class ForTestCompileSomething { - public static final boolean ACTUALLY_COMPILE = !"false".equals(System.getenv("kotlin.tests.actually.compile")); + public static final boolean ACTUALLY_COMPILE = "true".equals(System.getenv("kotlin.tests.actually.compile")); @NotNull private final String jarName; diff --git a/compiler/tests/org/jetbrains/jet/jetTestUtils.kt b/compiler/tests/org/jetbrains/jet/jetTestUtils.kt index 9acc5e7de04..f9ac89a5ef8 100644 --- a/compiler/tests/org/jetbrains/jet/jetTestUtils.kt +++ b/compiler/tests/org/jetbrains/jet/jetTestUtils.kt @@ -35,3 +35,31 @@ public fun CodeInsightTestFixture.configureWithExtraFile(path: String, extraName configureByFile(path) } } + +public fun String.trimIndent(): String { + val lines = split('\n') + + val firstNonEmpty = lines.firstOrNull { !it.trim().isEmpty() } + if (firstNonEmpty == null) { + return this + } + + val trimmedPrefix = firstNonEmpty.takeWhile { ch -> ch.isWhitespace() } + if (trimmedPrefix.isEmpty()) { + return this + } + + return lines.map { line -> + if (line.trim().isEmpty()) { + "" + } + else { + if (!line.startsWith(trimmedPrefix)) { + throw IllegalArgumentException( + """Invalid line "$line", ${trimmedPrefix.size} whitespace character are expected""") + } + + line.substring(trimmedPrefix.length) + } + }.joinToString(separator = "\n") +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstKotlinTestGenerated.java index 7a56fb31825..fcece966531 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstKotlinTestGenerated.java @@ -66,6 +66,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl doTest("compiler/testData/compileKotlinAgainstKotlin/ImportObject.A.kt"); } + @TestMetadata("InlinedConstants.A.kt") + public void testInlinedConstants() throws Exception { + doTest("compiler/testData/compileKotlinAgainstKotlin/InlinedConstants.A.kt"); + } + @TestMetadata("InnerClass.A.kt") public void testInnerClass() throws Exception { doTest("compiler/testData/compileKotlinAgainstKotlin/InnerClass.A.kt"); diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index 4f20fb8b50a..a28d2b7d79f 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -2593,6 +2593,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/prop/CollectionSize.kt"); } + @TestMetadata("Constants.kt") + public void testConstants() throws Exception { + doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/prop/Constants.kt"); + } + @TestMetadata("ExtValClass.kt") public void testExtValClass() throws Exception { doTestCompiledKotlin("compiler/testData/loadJava/compiledKotlin/prop/ExtValClass.kt"); diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java index 9ef982632ec..5ab9d342207 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java @@ -1061,6 +1061,11 @@ public class LazyResolveRecursiveComparingTestGenerated extends AbstractLazyReso doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/prop/CollectionSize.kt"); } + @TestMetadata("Constants.kt") + public void testConstants() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/prop/Constants.kt"); + } + @TestMetadata("ExtValClass.kt") public void testExtValClass() throws Exception { doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/prop/ExtValClass.kt"); diff --git a/compiler/tests/org/jetbrains/jet/parsing/JetParsingTestGenerated.java b/compiler/tests/org/jetbrains/jet/parsing/JetParsingTestGenerated.java index 5354505a960..17336c86494 100644 --- a/compiler/tests/org/jetbrains/jet/parsing/JetParsingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/parsing/JetParsingTestGenerated.java @@ -885,16 +885,81 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/psi/recovery"), Pattern.compile("^(.*)\\.kts?$"), true); } + @TestMetadata("DoWhileWithEmptyCondition.kt") + public void testDoWhileWithEmptyCondition() throws Exception { + doParsingTest("compiler/testData/psi/recovery/DoWhileWithEmptyCondition.kt"); + } + + @TestMetadata("DoWhileWithoutLPar.kt") + public void testDoWhileWithoutLPar() throws Exception { + doParsingTest("compiler/testData/psi/recovery/DoWhileWithoutLPar.kt"); + } + @TestMetadata("EnumEntryInitList.kt") public void testEnumEntryInitList() throws Exception { doParsingTest("compiler/testData/psi/recovery/EnumEntryInitList.kt"); } + @TestMetadata("ForEmptyParentheses.kt") + public void testForEmptyParentheses() throws Exception { + doParsingTest("compiler/testData/psi/recovery/ForEmptyParentheses.kt"); + } + + @TestMetadata("ForEmptyWithoutBody.kt") + public void testForEmptyWithoutBody() throws Exception { + doParsingTest("compiler/testData/psi/recovery/ForEmptyWithoutBody.kt"); + } + + @TestMetadata("ForNoBodyBeforeRBrace.kt") + public void testForNoBodyBeforeRBrace() throws Exception { + doParsingTest("compiler/testData/psi/recovery/ForNoBodyBeforeRBrace.kt"); + } + @TestMetadata("ForRecovery.kt") public void testForRecovery() throws Exception { doParsingTest("compiler/testData/psi/recovery/ForRecovery.kt"); } + @TestMetadata("ForWithOnlyOneLParInEOF.kt") + public void testForWithOnlyOneLParInEOF() throws Exception { + doParsingTest("compiler/testData/psi/recovery/ForWithOnlyOneLParInEOF.kt"); + } + + @TestMetadata("ForWithoutBodyInEOF.kt") + public void testForWithoutBodyInEOF() throws Exception { + doParsingTest("compiler/testData/psi/recovery/ForWithoutBodyInEOF.kt"); + } + + @TestMetadata("ForWithoutLPar.kt") + public void testForWithoutLPar() throws Exception { + doParsingTest("compiler/testData/psi/recovery/ForWithoutLPar.kt"); + } + + @TestMetadata("ForWithoutLParInEOF.kt") + public void testForWithoutLParInEOF() throws Exception { + doParsingTest("compiler/testData/psi/recovery/ForWithoutLParInEOF.kt"); + } + + @TestMetadata("ForWithoutParamButWithRange.kt") + public void testForWithoutParamButWithRange() throws Exception { + doParsingTest("compiler/testData/psi/recovery/ForWithoutParamButWithRange.kt"); + } + + @TestMetadata("ForWithoutRange.kt") + public void testForWithoutRange() throws Exception { + doParsingTest("compiler/testData/psi/recovery/ForWithoutRange.kt"); + } + + @TestMetadata("IfWithEmptyCondition.kt") + public void testIfWithEmptyCondition() throws Exception { + doParsingTest("compiler/testData/psi/recovery/IfWithEmptyCondition.kt"); + } + + @TestMetadata("IfWithoutLPar.kt") + public void testIfWithoutLPar() throws Exception { + doParsingTest("compiler/testData/psi/recovery/IfWithoutLPar.kt"); + } + @TestMetadata("ImportRecovery.kt") public void testImportRecovery() throws Exception { doParsingTest("compiler/testData/psi/recovery/ImportRecovery.kt"); @@ -950,6 +1015,26 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest { doParsingTest("compiler/testData/psi/recovery/ValueParameterNoTypeRecovery.kt"); } + @TestMetadata("WhenWithoutBraces.kt") + public void testWhenWithoutBraces() throws Exception { + doParsingTest("compiler/testData/psi/recovery/WhenWithoutBraces.kt"); + } + + @TestMetadata("WhileWithEmptyCondition.kt") + public void testWhileWithEmptyCondition() throws Exception { + doParsingTest("compiler/testData/psi/recovery/WhileWithEmptyCondition.kt"); + } + + @TestMetadata("WhileWithoutLPar.kt") + public void testWhileWithoutLPar() throws Exception { + doParsingTest("compiler/testData/psi/recovery/WhileWithoutLPar.kt"); + } + + @TestMetadata("WithWithoutInAndMultideclaration.kt") + public void testWithWithoutInAndMultideclaration() throws Exception { + doParsingTest("compiler/testData/psi/recovery/WithWithoutInAndMultideclaration.kt"); + } + } @TestMetadata("compiler/testData/psi/script") diff --git a/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 5899e002084..ae686135ce9 100644 --- a/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -503,7 +503,7 @@ public class JetTypeCheckerTest extends JetLiteFixture { for (String type : types) { typesToIntersect.add(makeType(type)); } - JetType result = TypeUtils.intersect(JetTypeChecker.INSTANCE, typesToIntersect); + JetType result = TypeUtils.intersect(JetTypeChecker.DEFAULT, typesToIntersect); // assertNotNull("Intersection is null for " + typesToIntersect, result); assertEquals(makeType(expected), result); } @@ -520,7 +520,7 @@ public class JetTypeCheckerTest extends JetLiteFixture { private void assertSubtypingRelation(String subtype, String supertype, boolean expected) { JetType typeNode1 = makeType(subtype); JetType typeNode2 = makeType(supertype); - boolean result = JetTypeChecker.INSTANCE.isSubtypeOf( + boolean result = JetTypeChecker.DEFAULT.isSubtypeOf( typeNode1, typeNode2); String modifier = expected ? "not " : ""; diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassDescriptor.kt index 01be75b4317..80b1b5a09ec 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassDescriptor.kt @@ -181,7 +181,7 @@ class LazyJavaClassDescriptor( val candidateReturnType = candidate.getReturnType() val currentMostSpecificReturnType = currentMostSpecificType.getReturnType() assert(candidateReturnType != null && currentMostSpecificReturnType != null, "$candidate, $currentMostSpecificReturnType") - if (JetTypeChecker.INSTANCE.isSubtypeOf(candidateReturnType!!, currentMostSpecificReturnType!!)) { + if (JetTypeChecker.DEFAULT.isSubtypeOf(candidateReturnType!!, currentMostSpecificReturnType!!)) { currentMostSpecificType = candidate } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/types/LazyJavaTypeResolver.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/types/LazyJavaTypeResolver.kt index 25ca250653d..b9f46f376cb 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/types/LazyJavaTypeResolver.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/types/LazyJavaTypeResolver.kt @@ -147,7 +147,7 @@ class LazyJavaTypeResolver( for (supertype in (classifier() as JavaTypeParameter).getUpperBounds()) { supertypesJet.add(transformJavaType(supertype, UPPER_BOUND.toAttributes())) } - return TypeUtils.intersect(JetTypeChecker.INSTANCE, supertypesJet) + return TypeUtils.intersect(JetTypeChecker.DEFAULT, supertypesJet) ?: ErrorUtils.createErrorType("Can't intersect upper bounds of " + javaType.getPresentableText()) } @@ -276,4 +276,4 @@ fun TypeUsage.toAttributes() = object : JavaTypeAttributes { override val howThisTypeIsUsedAccordingToAnnotations: TypeUsage get() = howThisTypeIsUsed override val isMarkedNotNull: Boolean = false -} \ No newline at end of file +} diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClass.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClass.java index 99cb3b5107d..e5f50dd853c 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClass.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClass.java @@ -62,6 +62,9 @@ public interface JavaClass extends JavaClassifier, JavaTypeParameterListOwner, J @NotNull OriginKind getOriginKind(); + @NotNull + JavaType createImmediateType(@NotNull JavaTypeSubstitutor substitutor); + enum OriginKind { COMPILED, SOURCE, diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeProvider.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeProvider.java index e29fbd2ea5e..b1d63f7e68a 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeProvider.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeProvider.java @@ -21,4 +21,13 @@ import org.jetbrains.annotations.NotNull; public interface JavaTypeProvider { @NotNull JavaType createJavaLangObjectType(); + + @NotNull + JavaWildcardType createUpperBoundWildcard(@NotNull JavaType bound); + + @NotNull + JavaWildcardType createLowerBoundWildcard(@NotNull JavaType bound); + + @NotNull + JavaWildcardType createUnboundedWildcard(); } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/DescriptorDeserializersStorage.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/DescriptorDeserializersStorage.java index 866c8899d95..48b03d61877 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/DescriptorDeserializersStorage.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/DescriptorDeserializersStorage.java @@ -87,9 +87,38 @@ public class DescriptorDeserializersStorage { @Override public KotlinJvmBinaryClass.AnnotationVisitor visitField(@NotNull Name name, @NotNull String desc, @Nullable Object initializer) { MemberSignature signature = MemberSignature.fromFieldNameAndDesc(name, desc); + if (initializer != null) { + Object normalizedValue; + if ("ZBCS".contains(desc)) { + int intValue = ((Integer) initializer).intValue(); + if ("Z".equals(desc)) { + normalizedValue = intValue != 0; + } + else if ("B".equals(desc)) { + normalizedValue = ((byte) intValue); + } + else if ("C".equals(desc)) { + normalizedValue = ((char) intValue); + } + else if ("S".equals(desc)) { + normalizedValue = ((short) intValue); + } + else { + throw new AssertionError(desc); + } + } + else { + normalizedValue = initializer; + } + propertyConstants.put(signature, ConstantsPackage.createCompileTimeConstant( - initializer, /* canBeUsedInAnnotation */ true, /* isPureIntConstant */ true, /* usesVariableAsConstant */ true, /* expectedType */ null)); + normalizedValue, + /* canBeUsedInAnnotation */ true, + /* isPureIntConstant */ true, + /* usesVariableAsConstant */ true, + /* expectedType */ null + )); } return new MemberAnnotationVisitor(signature); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/AbstractTypeParameterDescriptor.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/AbstractTypeParameterDescriptor.java index 9be787d0c5b..07994b4070a 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/AbstractTypeParameterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/AbstractTypeParameterDescriptor.java @@ -132,7 +132,7 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip private JetType computeUpperBoundsAsType() { Set upperBounds = getUpperBounds(); assert !upperBounds.isEmpty() : "Upper bound list is empty in " + getName(); - JetType upperBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds); + JetType upperBoundsAsType = TypeUtils.intersect(JetTypeChecker.DEFAULT, upperBounds); return upperBoundsAsType != null ? upperBoundsAsType : KotlinBuiltIns.getInstance().getNothingType(); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index 304d417863b..fd07e32b8ca 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import javax.rmi.CORBA.ClassDesc; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -232,9 +233,15 @@ public class DescriptorUtils { private static boolean isSubtypeOfClass(@NotNull JetType type, @NotNull DeclarationDescriptor superClass) { DeclarationDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); - if (descriptor != null && superClass == descriptor.getOriginal()) { - return true; + if (descriptor != null) { + DeclarationDescriptor originalDescriptor = descriptor.getOriginal(); + if (originalDescriptor instanceof ClassifierDescriptor + && superClass instanceof ClassifierDescriptor + && ((ClassifierDescriptor) superClass).getTypeConstructor().equals(((ClassifierDescriptor) originalDescriptor).getTypeConstructor())) { + return true; + } } + for (JetType superType : type.getConstructor().getSupertypes()) { if (isSubtypeOfClass(superType, superClass)) { return true; @@ -452,7 +459,7 @@ public class DescriptorUtils { JetType nullableString = TypeUtils.makeNullable(KotlinBuiltIns.getInstance().getStringType()); return "valueOf".equals(functionDescriptor.getName().asString()) && methodTypeParameters.size() == 1 - && JetTypeChecker.INSTANCE.isSubtypeOf(methodTypeParameters.get(0).getType(), nullableString); + && JetTypeChecker.DEFAULT.isSubtypeOf(methodTypeParameters.get(0).getType(), nullableString); } public static boolean isEnumValuesMethod(@NotNull FunctionDescriptor functionDescriptor) { diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java index 7c29790768c..09c3abc67a9 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -17,10 +17,13 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.base.Predicate; -import com.google.common.collect.*; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.intellij.util.containers.ContainerUtil; import kotlin.Function1; import kotlin.Unit; +import kotlin.jvm.KotlinSignature; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -31,12 +34,11 @@ import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeConstructor; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; +import org.jetbrains.jet.utils.DFS; import java.util.*; -import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.CONFLICT; -import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.INCOMPATIBLE; -import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE; +import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.*; public class OverridingUtil { @@ -111,7 +113,7 @@ public class OverridingUtil { JetType superValueParameterType = getUpperBound(superValueParameters.get(i)); JetType subValueParameterType = getUpperBound(subValueParameters.get(i)); // TODO: compare erasure - if (!JetTypeChecker.INSTANCE.equalTypes(superValueParameterType, subValueParameterType)) { + if (!JetTypeChecker.DEFAULT.equalTypes(superValueParameterType, subValueParameterType)) { return OverrideCompatibilityInfo.typeParameterNumberMismatch(); } } @@ -163,7 +165,7 @@ public class OverridingUtil { if (superReturnType != null && subReturnType != null) { boolean bothErrors = subReturnType.isError() && superReturnType.isError(); - if (!bothErrors && !JetTypeChecker.INSTANCE.isSubtypeOf(subReturnType, superReturnType, localEqualityAxioms)) { + if (!bothErrors && !JetTypeChecker.withAxioms(localEqualityAxioms).isSubtypeOf(subReturnType, superReturnType)) { return OverrideCompatibilityInfo.returnTypeMismatch(superReturnType, subReturnType); } } @@ -201,7 +203,7 @@ public class OverridingUtil { @NotNull JetTypeChecker.TypeConstructorEquality axioms ) { boolean bothErrors = typeInSuper.isError() && typeInSub.isError(); - if (!bothErrors && !JetTypeChecker.INSTANCE.equalTypes(typeInSuper, typeInSub, axioms)) { + if (!bothErrors && !JetTypeChecker.withAxioms(axioms).equalTypes(typeInSuper, typeInSub)) { return false; } return true; @@ -315,7 +317,7 @@ public class OverridingUtil { JetType bReturnType = b.getReturnType(); assert bReturnType != null; - return JetTypeChecker.INSTANCE.isSubtypeOf(aReturnType, bReturnType); + return JetTypeChecker.DEFAULT.isSubtypeOf(aReturnType, bReturnType); } if (a instanceof PropertyDescriptor) { assert b instanceof PropertyDescriptor : "b is " + b.getClass(); @@ -325,7 +327,7 @@ public class OverridingUtil { } // both vals - return JetTypeChecker.INSTANCE.isSubtypeOf(((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType()); + return JetTypeChecker.DEFAULT.isSubtypeOf(((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType()); } throw new IllegalArgumentException("Unexpected callable: " + a.getClass()); } @@ -512,6 +514,64 @@ public class OverridingUtil { return maxVisibility; } + + @NotNull + @KotlinSignature("fun getTopmostOverridenDescriptors(originalDescriptor: CallableDescriptor): List") + public static List getTopmostOverridenDescriptors(@NotNull CallableDescriptor originalDescriptor) { + return DFS.dfs( + Collections.singletonList(originalDescriptor), + new DFS.Neighbors() { + @NotNull + @Override + public Iterable getNeighbors(CallableDescriptor current) { + return current.getOverriddenDescriptors(); + } + }, + new DFS.CollectingNodeHandler>( + new ArrayList() + ) { + @Override + public void afterChildren(CallableDescriptor current) { + if (current.getOverriddenDescriptors().isEmpty()) { + result.add(current); + } + } + } + ); + } + + public static boolean traverseOverridenDescriptors( + @NotNull CallableDescriptor originalDescriptor, + @NotNull final Function1 handler + ) { + return DFS.dfs( + Collections.singletonList(originalDescriptor), + new DFS.Neighbors() { + @NotNull + @Override + public Iterable getNeighbors(CallableDescriptor current) { + return current.getOverriddenDescriptors(); + } + }, + new DFS.AbstractNodeHandler() { + private boolean result = true; + + @Override + public boolean beforeChildren(CallableDescriptor current) { + if (!handler.invoke(current)) { + result = false; + } + return result; + } + + @Override + public Boolean result() { + return result; + } + } + ); + } + public interface DescriptorSink { void addToScope(@NotNull CallableMemberDescriptor fakeOverride); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.java index 20ef01fb9f0..cb08c23f4b7 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.java @@ -197,7 +197,7 @@ public class TypeBoundsImpl implements TypeBounds { } Set upperBounds = filterBounds(bounds, BoundKind.UPPER_BOUND, values); - JetType intersectionOfUpperBounds = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds); + JetType intersectionOfUpperBounds = TypeUtils.intersect(JetTypeChecker.DEFAULT, upperBounds); if (!upperBounds.isEmpty() && intersectionOfUpperBounds != null) { if (tryPossibleAnswer(intersectionOfUpperBounds)) { return Collections.singleton(intersectionOfUpperBounds); @@ -216,19 +216,19 @@ public class TypeBoundsImpl implements TypeBounds { for (Bound bound : bounds) { switch (bound.kind) { case LOWER_BOUND: - if (!JetTypeChecker.INSTANCE.isSubtypeOf(bound.type, possibleAnswer)) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(bound.type, possibleAnswer)) { return false; } break; case UPPER_BOUND: - if (!JetTypeChecker.INSTANCE.isSubtypeOf(possibleAnswer, bound.type)) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(possibleAnswer, bound.type)) { return false; } break; case EXACT_BOUND: - if (!JetTypeChecker.INSTANCE.equalTypes(bound.type, possibleAnswer)) { + if (!JetTypeChecker.DEFAULT.equalTypes(bound.type, possibleAnswer)) { return false; } break; diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java index 4be5948ab9f..816fb52f8f3 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java @@ -352,7 +352,7 @@ public class WritableScopeImpl extends WritableScopeWithImports { for (VariableDescriptor oldProperty : properties) { ReceiverParameterDescriptor receiverParameterForOldVariable = oldProperty.getReceiverParameter(); if (((receiverParameter != null && receiverParameterForOldVariable != null) && - (JetTypeChecker.INSTANCE.equalTypes(receiverParameter.getType(), receiverParameterForOldVariable.getType())))) { + (JetTypeChecker.DEFAULT.equalTypes(receiverParameter.getType(), receiverParameterForOldVariable.getType())))) { redeclarationHandler.handleRedeclaration(oldProperty, variableDescriptor); } } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/AbstractJetType.java b/core/descriptors/src/org/jetbrains/jet/lang/types/AbstractJetType.java index d5ddee2fd74..4cbed4bca24 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/AbstractJetType.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/AbstractJetType.java @@ -37,7 +37,7 @@ public abstract class AbstractJetType implements JetType { JetType type = (JetType) obj; - return isNullable() == type.isNullable() && JetTypeChecker.INSTANCE.equalTypes(this, type); + return isNullable() == type.isNullable() && JetTypeChecker.DEFAULT.equalTypes(this, type); } @Override diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/CommonSupertypes.java b/core/descriptors/src/org/jetbrains/jet/lang/types/CommonSupertypes.java index 4c2eb28cd2c..100f56f3b9d 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/CommonSupertypes.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/CommonSupertypes.java @@ -216,7 +216,7 @@ public class CommonSupertypes { } if (ins != null) { - JetType intersection = TypeUtils.intersect(JetTypeChecker.INSTANCE, ins); + JetType intersection = TypeUtils.intersect(JetTypeChecker.DEFAULT, ins); if (intersection == null) { if (outs != null) { return new TypeProjectionImpl(OUT_VARIANCE, commonSupertype(outs)); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java b/core/descriptors/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java index 1d456a61807..3615141469b 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java @@ -147,13 +147,15 @@ public class DescriptorSubstitutor { }, new DFS.NodeHandlerWithListResult() { @Override - public void beforeChildren(JetType current) { + public boolean beforeChildren(JetType current) { ClassifierDescriptor declarationDescriptor = current.getConstructor().getDeclarationDescriptor(); // typeParameters in a list, but it contains very few elements, so it's fine to call contains() on it //noinspection SuspiciousMethodCalls if (typeParameters.contains(declarationDescriptor)) { result.add((TypeParameterDescriptor) declarationDescriptor); } + + return true; } } ); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeUtils.java index 47a5f1fcbe8..ecebe07b469 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -142,7 +142,7 @@ public class TypeUtils { } public static boolean isIntersectionEmpty(@NotNull JetType typeA, @NotNull JetType typeB) { - return intersect(JetTypeChecker.INSTANCE, Sets.newLinkedHashSet(Lists.newArrayList(typeA, typeB))) == null; + return intersect(JetTypeChecker.DEFAULT, Sets.newLinkedHashSet(Lists.newArrayList(typeA, typeB))) == null; } @Nullable @@ -376,9 +376,13 @@ public class TypeUtils { } private static void collectImmediateSupertypes(@NotNull JetType type, @NotNull Collection result) { + boolean isNullable = type.isNullable(); TypeSubstitutor substitutor = TypeSubstitutor.create(type); for (JetType supertype : type.getConstructor().getSupertypes()) { - result.add(substitutor.substitute(supertype, Variance.INVARIANT)); + JetType substitutedType = substitutor.substitute(supertype, Variance.INVARIANT); + if (substitutedType != null) { + result.add(makeNullableIfNeeded(substitutedType, isNullable)); + } } } @@ -469,7 +473,7 @@ public class TypeUtils { } public static boolean equalTypes(@NotNull JetType a, @NotNull JetType b) { - return JetTypeChecker.INSTANCE.isSubtypeOf(a, b) && JetTypeChecker.INSTANCE.isSubtypeOf(b, a); + return JetTypeChecker.DEFAULT.isSubtypeOf(a, b) && JetTypeChecker.DEFAULT.isSubtypeOf(b, a); } public static boolean dependsOnTypeParameters(@NotNull JetType type, @NotNull Collection typeParameters) { @@ -582,7 +586,7 @@ public class TypeUtils { return getDefaultPrimitiveNumberType(numberValueTypeConstructor); } for (JetType primitiveNumberType : numberValueTypeConstructor.getSupertypes()) { - if (JetTypeChecker.INSTANCE.isSubtypeOf(primitiveNumberType, expectedType)) { + if (JetTypeChecker.DEFAULT.isSubtypeOf(primitiveNumberType, expectedType)) { return primitiveNumberType; } } @@ -634,7 +638,7 @@ public class TypeUtils { }, new DFS.NodeHandlerWithListResult() { @Override - public void beforeChildren(JetType current) { + public boolean beforeChildren(JetType current) { TypeConstructor constructor = current.getConstructor(); Set instances = constructorToAllInstances.get(constructor); @@ -643,6 +647,8 @@ public class TypeUtils { constructorToAllInstances.put(constructor, instances); } instances.add(current); + + return true; } @Override diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/checker/JetTypeChecker.java b/core/descriptors/src/org/jetbrains/jet/lang/types/checker/JetTypeChecker.java index 9008697b8df..aaa4cc0a3b9 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/checker/JetTypeChecker.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/checker/JetTypeChecker.java @@ -22,39 +22,33 @@ import org.jetbrains.jet.lang.types.TypeConstructor; public class JetTypeChecker { - public static final JetTypeChecker INSTANCE = new JetTypeChecker(); public interface TypeConstructorEquality { boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b); } - private JetTypeChecker() { - } - - public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype) { - return TYPE_CHECKER.isSubtypeOf(subtype, supertype); - } - - public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull final TypeConstructorEquality equalityAxioms) { - return createWithAxioms(equalityAxioms).isSubtypeOf(subtype, supertype); - } - - public boolean equalTypes(@NotNull JetType a, @NotNull JetType b) { - return TYPE_CHECKER.equalTypes(a, b); - } - - public boolean equalTypes(@NotNull JetType a, @NotNull JetType b, @NotNull final TypeConstructorEquality equalityAxioms) { - return createWithAxioms(equalityAxioms).equalTypes(a, b); - } + public static final JetTypeChecker DEFAULT = new JetTypeChecker(new TypeCheckingProcedure(new TypeCheckerTypingConstraints())); @NotNull - private static TypeCheckingProcedure createWithAxioms(@NotNull final TypeConstructorEquality equalityAxioms) { - return new TypeCheckingProcedure(new TypeCheckerTypingConstraints() { + public static JetTypeChecker withAxioms(@NotNull final TypeConstructorEquality equalityAxioms) { + return new JetTypeChecker(new TypeCheckingProcedure(new TypeCheckerTypingConstraints() { @Override public boolean assertEqualTypeConstructors(@NotNull TypeConstructor constructor1, @NotNull TypeConstructor constructor2) { return constructor1.equals(constructor2) || equalityAxioms.equals(constructor1, constructor2); } - }); + })); } - private static final TypeCheckingProcedure TYPE_CHECKER = new TypeCheckingProcedure(new TypeCheckerTypingConstraints()); + private final TypeCheckingProcedure procedure; + + private JetTypeChecker(@NotNull TypeCheckingProcedure procedure) { + this.procedure = procedure; + } + + public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype) { + return procedure.isSubtypeOf(subtype, supertype); + } + + public boolean equalTypes(@NotNull JetType a, @NotNull JetType b) { + return procedure.equalTypes(a, b); + } } diff --git a/core/util.runtime/src/org/jetbrains/jet/utils/DFS.java b/core/util.runtime/src/org/jetbrains/jet/utils/DFS.java index 648b0215d5c..17e738c75a0 100644 --- a/core/util.runtime/src/org/jetbrains/jet/utils/DFS.java +++ b/core/util.runtime/src/org/jetbrains/jet/utils/DFS.java @@ -68,10 +68,9 @@ public class DFS { } private static void doDfs(@NotNull N current, @NotNull Neighbors neighbors, @NotNull Visited visited, @NotNull NodeHandler handler) { - if (!visited.checkAndMarkVisited(current)) { - return; - } - handler.beforeChildren(current); + if (!visited.checkAndMarkVisited(current)) return; + if (!handler.beforeChildren(current)) return; + for (N neighbor : neighbors.getNeighbors(current)) { doDfs(neighbor, neighbors, visited, handler); } @@ -79,8 +78,8 @@ public class DFS { } public interface NodeHandler { - @KotlinSignature("fun beforeChildren(current: N): Unit") - void beforeChildren(N current); + @KotlinSignature("fun beforeChildren(current: N): Boolean") + boolean beforeChildren(N current); @KotlinSignature("fun afterChildren(current: N): Unit") void afterChildren(N current); @@ -91,7 +90,7 @@ public class DFS { public interface Neighbors { @KotlinSignature("fun getNeighbors(current: N): Iterable") @NotNull - Iterable getNeighbors(N current); + Iterable getNeighbors(N current); } public interface Visited { @@ -100,7 +99,8 @@ public class DFS { public static abstract class AbstractNodeHandler implements NodeHandler { @Override - public void beforeChildren(N current) { + public boolean beforeChildren(N current) { + return true; } @Override diff --git a/eval4j/src/org/jetbrains/eval4j/interpreter.kt b/eval4j/src/org/jetbrains/eval4j/interpreter.kt index 90ade0434bc..c1d916f4fac 100644 --- a/eval4j/src/org/jetbrains/eval4j/interpreter.kt +++ b/eval4j/src/org/jetbrains/eval4j/interpreter.kt @@ -194,7 +194,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter( ObjectValue(value.obj(), targetType) } else { - throwEvalException(ClassCastException("Value '$value' cannot be cast to $targetType")) + throwEvalException(ClassCastException("${value.asmType.getClassName()} cannot be cast to ${targetType.getClassName()}")) } } diff --git a/eval4j/src/org/jetbrains/eval4j/interpreterLoop.kt b/eval4j/src/org/jetbrains/eval4j/interpreterLoop.kt index 1f63176ab82..e6712a16519 100644 --- a/eval4j/src/org/jetbrains/eval4j/interpreterLoop.kt +++ b/eval4j/src/org/jetbrains/eval4j/interpreterLoop.kt @@ -26,13 +26,20 @@ import org.jetbrains.org.objectweb.asm.tree.VarInsnNode import org.jetbrains.org.objectweb.asm.util.Printer import org.jetbrains.org.objectweb.asm.tree.TryCatchBlockNode import java.util.ArrayList +import org.jetbrains.eval4j.ExceptionThrown.ExceptionKind trait InterpreterResult { override fun toString(): String } -class ExceptionThrown(val exception: Value): InterpreterResult { - override fun toString(): String = "Thrown $exception" +class ExceptionThrown(val exception: Value, val kind: ExceptionKind): InterpreterResult { + override fun toString(): String = "Thrown $exception: $kind" + + enum class ExceptionKind { + FROM_EVALUATED_CODE + FROM_EVALUATOR + BROKEN_CODE + } } data class ValueReturned(val result: Value): InterpreterResult { @@ -60,10 +67,13 @@ trait InterpretationEventHandler { fun exceptionCaught(currentState: Frame, currentInsn: AbstractInsnNode, exception: Value): InterpreterResult? } -class ThrownFromEvalException(cause: Throwable): RuntimeException(cause) { +abstract class ThrownFromEvalExceptionBase(cause: Throwable): RuntimeException(cause) { override fun toString(): String = "Thrown by evaluator: ${getCause()}" } +class BrokenCode(cause: Throwable): ThrownFromEvalExceptionBase(cause) +class ThrownFromEvalException(cause: Throwable): ThrownFromEvalExceptionBase(cause) + class ThrownFromEvaluatedCodeException(val exception: Value): RuntimeException() { override fun toString(): String = "Thrown from evaluated code: $exception" } @@ -206,7 +216,7 @@ fun interpreterLoop( val handled = handler.exceptionThrown(frame, currentInsn, exceptionValue) if (handled != null) return handled if (exceptionCaught(exceptionValue)) continue - return ExceptionThrown(exceptionValue) + return ExceptionThrown(exceptionValue, ExceptionKind.FROM_EVALUATED_CODE) } // Workaround for a bug in Kotlin: NoPatterMatched exception is thrown otherwise! @@ -216,20 +226,22 @@ fun interpreterLoop( try { frame.execute(currentInsn, interpreter) } - catch (e: ThrownFromEvalException) { + catch (e: ThrownFromEvalExceptionBase) { val exception = e.getCause()!! val exceptionValue = ObjectValue(exception, Type.getType(exception.javaClass)) val handled = handler.exceptionThrown(frame, currentInsn, exceptionValue) if (handled != null) return handled if (exceptionFromEvalCaught(exception, exceptionValue)) continue - return ExceptionThrown(exceptionValue) + + val exceptionType = if (e is BrokenCode) ExceptionKind.BROKEN_CODE else ExceptionKind.FROM_EVALUATOR + return ExceptionThrown(exceptionValue, exceptionType) } catch (e: ThrownFromEvaluatedCodeException) { val handled = handler.exceptionThrown(frame, currentInsn, e.exception) if (handled != null) return handled if (exceptionCaught(e.exception)) continue - return ExceptionThrown(e.exception) + return ExceptionThrown(e.exception, ExceptionKind.FROM_EVALUATED_CODE) } } } @@ -245,7 +257,7 @@ fun interpreterLoop( } } -private fun Frame.getStackTop(i: Int = 0) = this.getStack(this.getStackSize() - 1 - i) ?: throwEvalException(IllegalArgumentException("Couldn't get value with index = $i from top of stack")) +private fun Frame.getStackTop(i: Int = 0) = this.getStack(this.getStackSize() - 1 - i) ?: throwBrokenCodeException(IllegalArgumentException("Couldn't get value with index = $i from top of stack")) // Copied from org.jetbrains.org.objectweb.asm.tree.analysis.Analyzer.analyze() fun computeHandlers(m: MethodNode): Array?> { diff --git a/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt b/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt index af6d60070b2..d0596a0c615 100644 --- a/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt +++ b/eval4j/src/org/jetbrains/eval4j/jdi/jdiEval.kt @@ -21,6 +21,8 @@ import org.jetbrains.org.objectweb.asm.Type import com.sun.jdi import com.sun.jdi.ClassNotLoadedException import com.sun.tools.jdi.ReferenceTypeImpl +import com.sun.jdi.ObjectReference +import com.sun.jdi.Method val CLASS = Type.getType(javaClass>()) val BOOTSTRAP_CLASS_DESCRIPTORS = setOf("Ljava/lang/String;", "Ljava/lang/ClassLoader;", "Ljava/lang/Class;") @@ -66,7 +68,7 @@ class JDIEval( ) } - override fun loadString(str: String): Value = vm.mirrorOf(str)!!.asValue() + override fun loadString(str: String): Value = vm.mirrorOf(str).asValue() override fun newInstance(classType: Type): Value { return NewObjectValue(classType) @@ -125,18 +127,28 @@ class JDIEval( } override fun getArrayElement(array: Value, index: Value): Value { - return array.array().getValue(index.int).asValue() + try { + return array.array().getValue(index.int).asValue() + } + catch (e: IndexOutOfBoundsException) { + throwEvalException(ArrayIndexOutOfBoundsException(e.getMessage())) + } } override fun setArrayElement(array: Value, index: Value, newValue: Value) { - array.array().setValue(index.int, newValue.asJdiValue(vm, array.asmType.arrayElementType)) + try { + return array.array().setValue(index.int, newValue.asJdiValue(vm, array.asmType.arrayElementType)) + } + catch (e: IndexOutOfBoundsException) { + throwEvalException(ArrayIndexOutOfBoundsException(e.getMessage())) + } } private fun findField(fieldDesc: FieldDescription): jdi.Field { val _class = fieldDesc.ownerType.asReferenceType() val field = _class.fieldByName(fieldDesc.name) if (field == null) { - throwEvalException(NoSuchFieldError("Field not found: $fieldDesc")) + throwBrokenCodeException(NoSuchFieldError("Field not found: $fieldDesc")) } return field } @@ -144,7 +156,7 @@ class JDIEval( private fun findStaticField(fieldDesc: FieldDescription): jdi.Field { val field = findField(fieldDesc) if (!field.isStatic()) { - throwEvalException(NoSuchFieldError("Field is not static: $fieldDesc")) + throwBrokenCodeException(NoSuchFieldError("Field is not static: $fieldDesc")) } return field } @@ -158,12 +170,12 @@ class JDIEval( val field = findStaticField(fieldDesc) if (field.isFinal()) { - throwEvalException(NoSuchFieldError("Can't modify a final field: $field")) + throwBrokenCodeException(NoSuchFieldError("Can't modify a final field: $field")) } val _class = field.declaringType() if (_class !is jdi.ClassType) { - throwEvalException(NoSuchFieldError("Can't a field in a non-class: $field")) + throwBrokenCodeException(NoSuchFieldError("Can't a field in a non-class: $field")) } val jdiValue = newValue.asJdiValue(vm, field.`type`().asType()) @@ -179,7 +191,7 @@ class JDIEval( else -> _class.methodsByName(methodDesc.name, methodDesc.desc) } if (method.isEmpty()) { - throwEvalException(NoSuchMethodError("Method not found: $methodDesc")) + throwBrokenCodeException(NoSuchMethodError("Method not found: $methodDesc")) } return method[0] } @@ -187,10 +199,10 @@ class JDIEval( override fun invokeStaticMethod(methodDesc: MethodDescription, arguments: List): Value { val method = findMethod(methodDesc) if (!method.isStatic()) { - throwEvalException(NoSuchMethodError("Method is not static: $methodDesc")) + throwBrokenCodeException(NoSuchMethodError("Method is not static: $methodDesc")) } val _class = method.declaringType() - if (_class !is jdi.ClassType) throwEvalException(NoSuchMethodError("Static method is a non-class type: $method")) + if (_class !is jdi.ClassType) throwBrokenCodeException(NoSuchMethodError("Static method is a non-class type: $method")) val args = mapArguments(arguments, method.safeArgumentTypes()) val result = mayThrow { _class.invokeMethod(thread, method, args, invokePolicy) } @@ -213,27 +225,31 @@ class JDIEval( } override fun invokeMethod(instance: Value, methodDesc: MethodDescription, arguments: List, invokespecial: Boolean): Value { - if (invokespecial) { - if (methodDesc.name == "") { - // Constructor call - val ctor = findMethod(methodDesc) - val _class = (instance as NewObjectValue).asmType.asReferenceType() as jdi.ClassType - val args = mapArguments(arguments, ctor.safeArgumentTypes()) - val result = mayThrow { _class.newInstance(thread, ctor, args, invokePolicy) } - instance.value = result - return result.asValue() - } - else { - // TODO - throw UnsupportedOperationException("invokespecial is not suported yet") - } + if (invokespecial && methodDesc.name == "") { + // Constructor call + val ctor = findMethod(methodDesc) + val _class = (instance as NewObjectValue).asmType.asReferenceType() as jdi.ClassType + val args = mapArguments(arguments, ctor.safeArgumentTypes()) + val result = mayThrow { _class.newInstance(thread, ctor, args, invokePolicy) } + instance.value = result + return result.asValue() + } + + fun doInvokeMethod(obj: ObjectReference, method: Method, policy: Int): Value { + val args = mapArguments(arguments, method.safeArgumentTypes()) + val result = mayThrow { obj.invokeMethod(thread, method, args, policy) } + return result.asValue() } val obj = instance.jdiObj.checkNull() - val method = findMethod(methodDesc, instance.jdiObj!!.referenceType() ?: methodDesc.ownerType.asReferenceType()) - val args = mapArguments(arguments, method.safeArgumentTypes()) - val result = mayThrow { obj.invokeMethod(thread, method, args, invokePolicy) } - return result.asValue() + if (invokespecial) { + val method = findMethod(methodDesc) + return doInvokeMethod(obj, method, invokePolicy or ObjectReference.INVOKE_NONVIRTUAL) + } + else { + val method = findMethod(methodDesc, obj.referenceType() ?: methodDesc.ownerType.asReferenceType()) + return doInvokeMethod(obj, method, invokePolicy) + } } private fun mapArguments(arguments: List, expecetedTypes: List): List { @@ -253,12 +269,7 @@ class JDIEval( val dimensions = name.count { it == '[' } val baseTypeName = if (dimensions > 0) name.substring(0, name.indexOf('[')) else name - val primitiveType = primitiveTypes[baseTypeName] - val baseType = if (primitiveType != null) - primitiveType - else { - Type.getType("L$baseTypeName;").asReferenceType() - } + val baseType = primitiveTypes[baseTypeName] ?: Type.getType("L$baseTypeName;").asReferenceType() if (dimensions == 0) baseType diff --git a/eval4j/src/org/jetbrains/eval4j/jdi/jdiValues.kt b/eval4j/src/org/jetbrains/eval4j/jdi/jdiValues.kt index 1c10c518841..d665acfd1a3 100644 --- a/eval4j/src/org/jetbrains/eval4j/jdi/jdiValues.kt +++ b/eval4j/src/org/jetbrains/eval4j/jdi/jdiValues.kt @@ -25,22 +25,25 @@ import com.sun.jdi fun makeInitialFrame(methodNode: MethodNode, arguments: List): Frame { val isStatic = (methodNode.access and ACC_STATIC) != 0 - assert(isStatic, "Instance methods are not supported: $methodNode") val params = Type.getArgumentTypes(methodNode.desc) - assert(params.size == arguments.size(), "Wrong number of arguments for $methodNode: $arguments") + assert(arguments.size() == (if (isStatic) params.size else params.size + 1), "Wrong number of arguments for $methodNode: $arguments") val frame = Frame(methodNode.maxLocals, methodNode.maxStack) frame.setReturn(makeNotInitializedValue(Type.getReturnType(methodNode.desc))) + var index = 0 for ((i, arg) in arguments.withIndices()) { - frame.setLocal(i, arg) + frame.setLocal(index++, arg) + if (arg.getSize() == 2) { + frame.setLocal(index++, NOT_A_VALUE) + } } - for (i in arguments.size..methodNode.maxLocals - 1) { - frame.setLocal(i, NOT_A_VALUE) + while (index < methodNode.maxLocals) { + frame.setLocal(index++, NOT_A_VALUE) } - + return frame } diff --git a/eval4j/src/org/jetbrains/eval4j/values.kt b/eval4j/src/org/jetbrains/eval4j/values.kt index 4e15b5adda2..971aa6ad9f3 100644 --- a/eval4j/src/org/jetbrains/eval4j/values.kt +++ b/eval4j/src/org/jetbrains/eval4j/values.kt @@ -129,4 +129,8 @@ fun T?.checkNull(): T { fun throwEvalException(e: Throwable): Nothing { throw ThrownFromEvalException(e) +} + +fun throwBrokenCodeException(e: Throwable): Nothing { + throw BrokenCode(e) } \ No newline at end of file diff --git a/eval4j/test/org/jetbrains/eval4j/jdi/test/jdiTest.kt b/eval4j/test/org/jetbrains/eval4j/jdi/test/jdiTest.kt index e1bf8a7dcbb..41968f8e2f6 100644 --- a/eval4j/test/org/jetbrains/eval4j/jdi/test/jdiTest.kt +++ b/eval4j/test/org/jetbrains/eval4j/jdi/test/jdiTest.kt @@ -21,15 +21,15 @@ import com.sun.jdi import junit.framework.TestSuite import org.jetbrains.eval4j.test.buildTestSuite import junit.framework.TestCase -import org.jetbrains.eval4j.interpreterLoop import org.junit.Assert.* import java.util.concurrent.CountDownLatch import java.util.concurrent.atomic.AtomicInteger -import org.jetbrains.eval4j.ExceptionThrown -import org.jetbrains.eval4j.MethodDescription -import org.jetbrains.eval4j.ValueReturned import org.jetbrains.eval4j.jdi.* import java.io.File +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.eval4j.test.getTestName +import com.sun.jdi.ObjectReference val DEBUGEE_CLASS = javaClass() @@ -98,15 +98,24 @@ fun suite(): TestSuite { val suite = buildTestSuite { methodNode, ownerClass, expected -> remainingTests.incrementAndGet() - object : TestCase("test" + methodNode.name.capitalize()) { + object : TestCase(getTestName(methodNode.name)) { override fun runTest() { - val eval = JDIEval( - vm, classLoader!!, thread!!, 0 - ) + val eval = JDIEval(vm, classLoader!!, thread!!, 0) + + val args = if ((methodNode.access and Opcodes.ACC_STATIC) == 0) { + // Instance method + val newInstance = eval.newInstance(Type.getType(ownerClass)) + val thisValue = eval.invokeMethod(newInstance, MethodDescription(ownerClass.getName(), "", "()V", false), listOf(), true) + listOf(thisValue) + } + else { + listOf() + } + val value = interpreterLoop( methodNode, - makeInitialFrame(methodNode, listOf()), + makeInitialFrame(methodNode, args), eval ) @@ -125,14 +134,14 @@ fun suite(): TestSuite { } try { - if (value is ExceptionThrown) { - val str = value.exception.jdiObj.callToString() - System.err.println("Exception: $str") - } - if (expected is ValueReturned && value is ValueReturned && value.result is ObjectValue) { assertEquals(expected.result.obj().toString(), value.result.jdiObj.callToString()) } + else if (expected is ExceptionThrown && value is ExceptionThrown) { + val valueObj = value.exception.obj() + val actual = if (valueObj is ObjectReference) valueObj.callToString() else valueObj.toString() + assertEquals(expected.exception.obj().toString(), actual) + } else { assertEquals(expected, value) } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClass.kt b/eval4j/test/org/jetbrains/eval4j/test/BaseTestData.java similarity index 53% rename from j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClass.kt rename to eval4j/test/org/jetbrains/eval4j/test/BaseTestData.java index ac6dc1a4c88..514d24c0cf5 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClass.kt +++ b/eval4j/test/org/jetbrains/eval4j/test/BaseTestData.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * Copyright 2010-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,20 +14,12 @@ * limitations under the License. */ -package org.jetbrains.jet.j2k.ast +package org.jetbrains.eval4j.test; -import org.jetbrains.jet.j2k.Converter -import java.util.Collections +class BaseTestData { + String superCall() { + return "Base"; + } -class AnonymousClass(converter: Converter, bodyElements: List) -: Class(converter, - Identifier("anonClass"), - MemberComments.Empty, - Collections.emptySet(), - TypeParameterList.Empty, - listOf(), - listOf(), - listOf(), - bodyElements) { - override fun toKotlin() = bodyToKotlin() -} + private String invokeSpecialPrivateFun(String s) { return "Derived"; } +} \ No newline at end of file diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/Dispatcher.kt b/eval4j/test/org/jetbrains/eval4j/test/IgnoreInReflectionTests.java similarity index 63% rename from j2k/src/org/jetbrains/jet/j2k/visitors/Dispatcher.kt rename to eval4j/test/org/jetbrains/eval4j/test/IgnoreInReflectionTests.java index 13519d0dbce..f07142feff6 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/Dispatcher.kt +++ b/eval4j/test/org/jetbrains/eval4j/test/IgnoreInReflectionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * Copyright 2010-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,11 @@ * limitations under the License. */ -package org.jetbrains.jet.j2k.visitors +package org.jetbrains.eval4j.test; -import org.jetbrains.jet.j2k.Converter -import org.jetbrains.jet.j2k.TypeConverter +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; -open class Dispatcher(converter: Converter, typeConverter: TypeConverter) { - var expressionVisitor: ExpressionVisitor = ExpressionVisitor(converter, typeConverter) +@Retention(RetentionPolicy.RUNTIME) +public @interface IgnoreInReflectionTests { } diff --git a/eval4j/test/org/jetbrains/eval4j/test/TestData.java b/eval4j/test/org/jetbrains/eval4j/test/TestData.java index 4efccd6967f..a1b80b86914 100644 --- a/eval4j/test/org/jetbrains/eval4j/test/TestData.java +++ b/eval4j/test/org/jetbrains/eval4j/test/TestData.java @@ -16,8 +16,8 @@ package org.jetbrains.eval4j.test; -class TestData { - static void returnVoid() { +class TestData extends BaseTestData { + static void returnVoid() { } static boolean returnBoolean() { @@ -691,6 +691,98 @@ class TestData { long l = 1; Long[] IFEQ_L = new Long[] { b ? 100L : 200L }; } + + @Override + String superCall() { + return "Derived"; + } + + @IgnoreInReflectionTests + String testInvokeSpecialForSuperCall() { + return super.superCall(); + } + + @IgnoreInReflectionTests + static String testInvokeSpecial() { + TestData td = new TestData(); + return td.invokeSpecialPrivateFun(""); + } + + private String invokeSpecialPrivateFun(String s) { return "Base"; } + + static Throwable exception1() { + throw new IllegalStateException(); + } + + static void exception2() { + new ExceptionsTest().f1(); + } + + static void exceptionClassCast() { + ExceptionsTest.Derived test = (ExceptionsTest.Derived) new ExceptionsTest.Base(); + } + + static class ExceptionsTest { + void f1() { + throw new IllegalStateException(); + } + + static class Base {} + static class Derived extends Base {} + } + + static boolean exceptionIndexOutOfBounds() { + int[] ints = new int[1]; + try { int i = ints[2]; return false; } catch (ArrayIndexOutOfBoundsException e) { } + try { ints[2] = 1; return false; } catch (ArrayIndexOutOfBoundsException e) { } + + short[] shorts = new short[1]; + try { short s = shorts[2]; return false; } catch (ArrayIndexOutOfBoundsException e) { } + try { shorts[2] = 1; return false; } catch (ArrayIndexOutOfBoundsException e) { } + + char[] chars = new char[1]; + try { char c = chars[2]; return false; } catch (ArrayIndexOutOfBoundsException e) { } + try { chars[2] = 1; return false; } catch (ArrayIndexOutOfBoundsException e) { } + + byte[] bytes = new byte[1]; + try { byte b = bytes[2]; return false; } catch (ArrayIndexOutOfBoundsException e) { } + try { bytes[2] = 1; return false; } catch (ArrayIndexOutOfBoundsException e) { } + + long[] longs = new long[1]; + try { long l = longs[2]; return false; } catch (ArrayIndexOutOfBoundsException e) { } + try { longs[2] = 1; return false; } catch (ArrayIndexOutOfBoundsException e) { } + + double[] doubles = new double[1]; + try { double d = doubles[2]; return false; } catch (ArrayIndexOutOfBoundsException e) { } + try { doubles[2] = 1.0; return false; } catch (ArrayIndexOutOfBoundsException e) { } + + float[] floats = new float[1]; + try { float f = floats[2]; return false; } catch (ArrayIndexOutOfBoundsException e) { } + try { floats[2] = 1; return false; } catch (ArrayIndexOutOfBoundsException e) { } + + boolean[] booleans = new boolean[1]; + try { boolean bool = booleans[2];return false; } catch (ArrayIndexOutOfBoundsException e) { } + try { booleans[2] = true; return false; } catch (ArrayIndexOutOfBoundsException e) { } + + Object[] objects = new Object[1]; + try { Object o = objects[2]; return false; } catch (ArrayIndexOutOfBoundsException e) { } + try { objects[2] = 1; return false; } catch (ArrayIndexOutOfBoundsException e) { } + + return true; + } + + static boolean indexOutOfBoundsForString() { + String str = ""; + try { str.charAt(10); return false; } catch (IndexOutOfBoundsException e) { } + try { str.substring(10); return false; } catch (IndexOutOfBoundsException e) { } + + return true; + } + + public TestData() { + } } + + diff --git a/eval4j/test/org/jetbrains/eval4j/test/main.kt b/eval4j/test/org/jetbrains/eval4j/test/main.kt index 0ec942f1710..bff0af3c707 100644 --- a/eval4j/test/org/jetbrains/eval4j/test/main.kt +++ b/eval4j/test/org/jetbrains/eval4j/test/main.kt @@ -33,19 +33,34 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Frame fun suite(): TestSuite = buildTestSuite { methodNode, ownerClass, expected -> - object : TestCase("test" + methodNode.name.capitalize()) { + object : TestCase(getTestName(methodNode.name)) { override fun runTest() { - val value = interpreterLoop( - methodNode, - initFrame( - ownerClass.getInternalName(), - methodNode - ), - REFLECTION_EVAL - ) + if (!isIgnored(methodNode)) { + val value = interpreterLoop( + methodNode, + initFrame( + ownerClass.getInternalName(), + methodNode + ), + REFLECTION_EVAL + ) + + if (expected is ExceptionThrown && value is ExceptionThrown) { + assertEquals(expected.exception.toString(), value.exception.toString()) + } + else { + assertEquals(expected.toString(), value.toString()) + } + } + } - assertEquals(expected, value) + private fun isIgnored(methodNode: MethodNode): Boolean { + return methodNode.visibleAnnotations?.any { + val annotationDesc = it.desc + annotationDesc != null && + Type.getType(annotationDesc) == Type.getType(javaClass()) + } ?: false } } } @@ -62,7 +77,9 @@ fun initFrame( var local = 0 if ((m.access and ACC_STATIC) == 0) { val ctype = Type.getObjectType(owner) - current.setLocal(local++, makeNotInitializedValue(ctype)) + val newInstance = REFLECTION_EVAL.newInstance(ctype) + val thisValue = REFLECTION_EVAL.invokeMethod(newInstance, MethodDescription(owner, "", "()V", false), listOf(), true) + current.setLocal(local++, thisValue) } val args = Type.getArgumentTypes(m.desc) @@ -133,21 +150,23 @@ object REFLECTION_EVAL : Eval { val elementType = if (asmType.getDimensions() == 1) asmType.getElementType() else Type.getType(asmType.getDescriptor().substring(1)) val arr = array.obj().checkNull() val ind = index.int - return when (elementType.getSort()) { - Type.BOOLEAN -> boolean(JArray.getBoolean(arr, ind)) - Type.BYTE -> byte(JArray.getByte(arr, ind)) - Type.SHORT -> short(JArray.getShort(arr, ind)) - Type.CHAR -> char(JArray.getChar(arr, ind)) - Type.INT -> int(JArray.getInt(arr, ind)) - Type.LONG -> long(JArray.getLong(arr, ind)) - Type.FLOAT -> float(JArray.getFloat(arr, ind)) - Type.DOUBLE -> double(JArray.getDouble(arr, ind)) - Type.OBJECT, - Type.ARRAY -> { - val value = JArray.get(arr, ind) - if (value == null) NULL_VALUE else ObjectValue(value, Type.getType(value.javaClass)) + return mayThrow { + when (elementType.getSort()) { + Type.BOOLEAN -> boolean(JArray.getBoolean(arr, ind)) + Type.BYTE -> byte(JArray.getByte(arr, ind)) + Type.SHORT -> short(JArray.getShort(arr, ind)) + Type.CHAR -> char(JArray.getChar(arr, ind)) + Type.INT -> int(JArray.getInt(arr, ind)) + Type.LONG -> long(JArray.getLong(arr, ind)) + Type.FLOAT -> float(JArray.getFloat(arr, ind)) + Type.DOUBLE -> double(JArray.getDouble(arr, ind)) + Type.OBJECT, + Type.ARRAY -> { + val value = JArray.get(arr, ind) + if (value == null) NULL_VALUE else ObjectValue(value, Type.getType(value.javaClass)) + } + else -> throw UnsupportedOperationException("Unsupported array element type: $elementType") } - else -> throw UnsupportedOperationException("Unsupported array element type: $elementType") } } @@ -159,20 +178,22 @@ object REFLECTION_EVAL : Eval { return } val elementType = array.asmType.getElementType() - when (elementType.getSort()) { - Type.BOOLEAN -> JArray.setBoolean(arr, ind, newValue.boolean) - Type.BYTE -> JArray.setByte(arr, ind, newValue.int.toByte()) - Type.SHORT -> JArray.setShort(arr, ind, newValue.int.toShort()) - Type.CHAR -> JArray.setChar(arr, ind, newValue.int.toChar()) - Type.INT -> JArray.setInt(arr, ind, newValue.int) - Type.LONG -> JArray.setLong(arr, ind, newValue.long) - Type.FLOAT -> JArray.setFloat(arr, ind, newValue.float) - Type.DOUBLE -> JArray.setDouble(arr, ind, newValue.double) - Type.OBJECT, - Type.ARRAY -> { - JArray.set(arr, ind, newValue.obj()) + mayThrow { + when (elementType.getSort()) { + Type.BOOLEAN -> JArray.setBoolean(arr, ind, newValue.boolean) + Type.BYTE -> JArray.setByte(arr, ind, newValue.int.toByte()) + Type.SHORT -> JArray.setShort(arr, ind, newValue.int.toShort()) + Type.CHAR -> JArray.setChar(arr, ind, newValue.int.toChar()) + Type.INT -> JArray.setInt(arr, ind, newValue.int) + Type.LONG -> JArray.setLong(arr, ind, newValue.long) + Type.FLOAT -> JArray.setFloat(arr, ind, newValue.float) + Type.DOUBLE -> JArray.setDouble(arr, ind, newValue.double) + Type.OBJECT, + Type.ARRAY -> { + JArray.set(arr, ind, newValue.obj()) + } + else -> throw UnsupportedOperationException("Unsupported array element type: $elementType") } - else -> throw UnsupportedOperationException("Unsupported array element type: $elementType") } } @@ -265,7 +286,7 @@ object REFLECTION_EVAL : Eval { } else { // TODO - throw UnsupportedOperationException("invokespecial is not suported yet") + throw UnsupportedOperationException("invokespecial is not suported in reflection eval") } } val obj = instance.obj().checkNull() diff --git a/eval4j/test/org/jetbrains/eval4j/test/suiteBuilder.kt b/eval4j/test/org/jetbrains/eval4j/test/suiteBuilder.kt index 9de6ed4cd4a..eecfeac02f1 100644 --- a/eval4j/test/org/jetbrains/eval4j/test/suiteBuilder.kt +++ b/eval4j/test/org/jetbrains/eval4j/test/suiteBuilder.kt @@ -63,22 +63,27 @@ fun buildTestCase(ownerClass: Class, var expected: InterpreterResult? = null for (method in ownerClass.getDeclaredMethods()) { if (method.getName() == methodNode.name) { - if ((method.getModifiers() and Modifier.STATIC) == 0) { - println("Skipping instance method: $method") - } - else if (method.getParameterTypes()!!.size > 0) { + val isStatic = (method.getModifiers() and Modifier.STATIC) != 0 + if (method.getParameterTypes()!!.size > 0) { println("Skipping method with parameters: $method") } + else if (!isStatic && !method.getName()!!.startsWith("test")) { + println("Skipping instance method (should be started with 'test') : $method") + } else { method.setAccessible(true) - val result = method.invoke(null) - val returnType = Type.getType(method.getReturnType()!!) try { + val result = method.invoke(if (isStatic) null else ownerClass.newInstance()) + val returnType = Type.getType(method.getReturnType()!!) expected = ValueReturned(objectToValue(result, returnType)) } catch (e: UnsupportedOperationException) { println("Skipping $method: $e") } + catch (e: Throwable) { + val cause = e.getCause() ?: e + expected = ExceptionThrown(objectToValue(cause, Type.getType(cause.javaClass)), ExceptionThrown.ExceptionKind.FROM_EVALUATOR) + } } } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Node.kt b/eval4j/test/org/jetbrains/eval4j/test/util.kt similarity index 74% rename from j2k/src/org/jetbrains/jet/j2k/ast/Node.kt rename to eval4j/test/org/jetbrains/eval4j/test/util.kt index 39e27714dab..5813cf5579b 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Node.kt +++ b/eval4j/test/org/jetbrains/eval4j/test/util.kt @@ -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. @@ -14,9 +14,6 @@ * limitations under the License. */ -package org.jetbrains.jet.j2k.ast +package org.jetbrains.eval4j.test - -trait Node { - public fun toKotlin(): String -} +fun getTestName(methodName: String) = if (methodName.startsWith("test")) methodName else "test${methodName.capitalize()}" \ No newline at end of file diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt index 6ae85ebc612..835a0d55f15 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -115,6 +115,7 @@ import org.jetbrains.jet.plugin.structureView.AbstractKotlinFileStructureTest import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterTest import org.jetbrains.jet.jps.build.AbstractIncrementalJpsTest import org.jetbrains.jet.asJava.AbstractKotlinLightClassTest +import org.jetbrains.jet.lang.resolve.java.AbstractJavaTypeSubstitutorTest fun main(args: Array) { System.setProperty("java.awt.headless", "true") @@ -271,6 +272,11 @@ fun main(args: Array) { } testGroup("idea/tests", "idea/testData") { + + testClass(javaClass()) { + model("typeSubstitution", extension = "java") + } + testClass(javaClass()) { model("resolve/additionalLazyResolve", testMethod = "doTest") } @@ -612,7 +618,8 @@ fun main(args: Array) { } testClass(javaClass()) { - model("debugger/tinyApp/src/evaluate") + model("debugger/tinyApp/src/evaluate/singleBreakpoint", testMethod = "doSingleBreakpointTest") + model("debugger/tinyApp/src/evaluate/multipleBreakpoints", testMethod = "doMultipleBreakpointsTest") } testClass(javaClass()) { diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 051feb4d07b..3908c869f2d 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -155,6 +155,9 @@ + + @@ -287,6 +290,7 @@ + diff --git a/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinAction.java b/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinAction.java index e434f58b207..a8250c61b51 100644 --- a/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinAction.java +++ b/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinAction.java @@ -16,7 +16,6 @@ package org.jetbrains.jet.plugin.actions; -import com.intellij.ide.highlighter.JavaFileType; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; @@ -25,10 +24,11 @@ import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiJavaFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.j2k.Converter; import org.jetbrains.jet.j2k.ConverterSettings; +import org.jetbrains.jet.j2k.FilesConversionScope; import java.util.List; @@ -43,7 +43,7 @@ public class JavaToKotlinAction extends AnAction { assert virtualFiles != null; final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); assert project != null; - final List selectedJavaFiles = getAllJavaFiles(virtualFiles, project); + final List selectedJavaFiles = getAllJavaFiles(virtualFiles, project); if (selectedJavaFiles.isEmpty()) { return; } @@ -52,7 +52,7 @@ public class JavaToKotlinAction extends AnAction { return; } - final Converter converter = prepareConverter(project, selectedJavaFiles); + final Converter converter = Converter.object$.create(project, ConverterSettings.defaultSettings, new FilesConversionScope(selectedJavaFiles)); CommandProcessor.getInstance().executeCommand( project, new Runnable() { @@ -76,18 +76,6 @@ public class JavaToKotlinAction extends AnAction { ); } - @NotNull - private static Converter prepareConverter(@NotNull Project project, @NotNull List selectedJavaFiles) { - Converter converter = new Converter(project, ConverterSettings.defaultSettings); - converter.clearClassIdentifiers(); - for (PsiFile f : selectedJavaFiles) { - if (f.getFileType() instanceof JavaFileType) { - setClassIdentifiers(converter, f); - } - } - return converter; - } - private static enum DialogResult { BACKUP_FILES, DELETE_FILES, diff --git a/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinActionUtil.java b/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinActionUtil.java index 9f3c3c2729d..5047f3e56f0 100644 --- a/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinActionUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/actions/JavaToKotlinActionUtil.java @@ -16,7 +16,6 @@ package org.jetbrains.jet.plugin.actions; -import com.intellij.ide.highlighter.JavaFileType; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ex.MessagesEx; @@ -29,19 +28,11 @@ import com.intellij.psi.codeStyle.CodeStyleManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.j2k.Converter; -import org.jetbrains.jet.j2k.visitors.ClassVisitor; import java.io.IOException; import java.util.*; public class JavaToKotlinActionUtil { - - static void setClassIdentifiers(@NotNull Converter converter, @NotNull PsiFile psiFile) { - ClassVisitor c = new ClassVisitor(); - psiFile.accept(c); - converter.setClassIdentifiers(new HashSet(c.getClassIdentifiers())); - } - @NotNull private static List getChildrenRecursive(@Nullable VirtualFile baseDir) { List result = new LinkedList(); @@ -53,14 +44,14 @@ public class JavaToKotlinActionUtil { } @NotNull - /*package*/ static List getAllJavaFiles(@NotNull VirtualFile[] vFiles, Project project) { + /*package*/ static List getAllJavaFiles(@NotNull VirtualFile[] vFiles, Project project) { Set filesSet = allVirtualFiles(vFiles); PsiManager manager = PsiManager.getInstance(project); - List res = new ArrayList(); + List res = new ArrayList(); for (VirtualFile file : filesSet) { PsiFile psiFile = manager.findFile(file); - if (psiFile != null && psiFile.getFileType() instanceof JavaFileType) { - res.add(psiFile); + if (psiFile != null && psiFile instanceof PsiJavaFile) { + res.add((PsiJavaFile)psiFile); } } return res; @@ -92,7 +83,7 @@ public class JavaToKotlinActionUtil { } @NotNull - static List convertFiles(final Converter converter, List allJavaFilesNear) { + static List convertFiles(final Converter converter, List allJavaFilesNear) { final List result = new LinkedList(); for (final PsiFile f : allJavaFilesNear) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @@ -108,7 +99,7 @@ public class JavaToKotlinActionUtil { return result; } - static void deleteFiles(List allJavaFilesNear) { + static void deleteFiles(List allJavaFilesNear) { for (final PsiFile f : allJavaFilesNear) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override @@ -133,7 +124,7 @@ public class JavaToKotlinActionUtil { if (psiFile instanceof PsiJavaFile && virtualFile != null) { String result = ""; try { - result = converter.convertFile((PsiJavaFile) psiFile).toKotlin(); + result = converter.elementToKotlin(psiFile); } catch (Exception e) { //noinspection CallToPrintStackTrace e.printStackTrace(); @@ -150,7 +141,7 @@ public class JavaToKotlinActionUtil { return null; } - static void renameFiles(@NotNull List psiFiles) { + static void renameFiles(@NotNull List psiFiles) { for (final PsiFile f : psiFiles) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/CodeInsightUtils.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/CodeInsightUtils.java index 54c3f66f5a9..df5de6eddd7 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/CodeInsightUtils.java +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/CodeInsightUtils.java @@ -97,7 +97,7 @@ public class CodeInsightUtils { } if (endOffset != element2.getTextRange().getEndOffset()) return PsiElement.EMPTY_ARRAY; - ArrayList array = new ArrayList(); + List array = new ArrayList(); PsiElement stopElement = element2.getNextSibling(); for (PsiElement currentElement = element1; currentElement != stopElement; currentElement = currentElement.getNextSibling()) { if (!(currentElement instanceof PsiWhiteSpace)) { diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt b/idea/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt index 6d1aa4df7fc..e75d61165c7 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt @@ -33,9 +33,11 @@ import org.jetbrains.jet.lang.resolve.java.descriptor.JavaPropertyDescriptor import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyPackageFragmentForJavaClass import org.jetbrains.jet.lang.resolve.java.descriptor.JavaMethodDescriptor import com.intellij.openapi.util.TextRange -import com.intellij.psi.SmartPointerManager import com.intellij.psi.PsiDocumentManager import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession +import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.jet.renderer.DescriptorRenderer.FQ_NAMES_IN_TYPES public object ShortenReferences { public fun process(element: JetElement) { @@ -100,6 +102,8 @@ public object ShortenReferences { private fun process(elements: Iterable, elementFilter: (PsiElement) -> FilterResult) { for ((file, fileElements) in elements.groupBy { element -> element.getContainingJetFile() }) { + ImportInsertHelper.optimizeImportsIfNeeded(file) + // first resolve all qualified references - optimization val referenceToContext = JetFileReferencesResolver.resolve(file, fileElements, visitShortNames = false) @@ -313,7 +317,13 @@ public object ShortenReferences { private fun resolveState(referenceExpression: JetReferenceExpression, bindingContext: BindingContext): Any? { val target = bindingContext[BindingContext.REFERENCE_TARGET, referenceExpression] - if (target != null) return target.asString() + if (target != null) { + val resolvedCallKey = (referenceExpression.getParent() as? JetThisExpression) ?: referenceExpression + val resolvedCall = bindingContext[BindingContext.RESOLVED_CALL, resolvedCallKey] + if (resolvedCall != null) return resolvedCall.asString() + + return target.asString() + } val targets = bindingContext[BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression] if (targets != null) return HashSet(targets.map{it.asString()}) @@ -334,8 +344,12 @@ public object ShortenReferences { private fun DeclarationDescriptor.asString() = DescriptorRenderer.FQ_NAMES_IN_TYPES.render(this) + private fun ResolvedCall<*>.asString(): String { + return "${getReceiverArgument()}, ${getThisObject()} -> ${getResultingDescriptor()?.let {FQ_NAMES_IN_TYPES.render(it)}}" + } + //TODO: do we need this "IfNeeded" check? private fun addImportIfNeeded(descriptor: DeclarationDescriptor, file: JetFile) { - ImportInsertHelper.addImportDirectiveIfNeeded(DescriptorUtils.getFqNameSafe(descriptor), file) + ImportInsertHelper.addImportDirectiveIfNeeded(DescriptorUtils.getFqNameSafe(descriptor), file, false) } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt index 7300d4bf674..ebc4e640e5d 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt @@ -172,7 +172,7 @@ fun createLookupElement(descriptor: DeclarationDescriptor, resolveSession: Resol return if (descriptor is FunctionDescriptor && descriptor.getValueParameters().isNotEmpty()) element.keepOldArgumentListOnTab() else element } -fun JetType.isSubtypeOf(expectedType: JetType) = !isError() && JetTypeChecker.INSTANCE.isSubtypeOf(this, expectedType) +fun JetType.isSubtypeOf(expectedType: JetType) = !isError() && JetTypeChecker.DEFAULT.isSubtypeOf(this, expectedType) fun T?.toList(): List = if (this != null) listOf(this) else listOf() fun T?.toSet(): Set = if (this != null) setOf(this) else setOf() diff --git a/idea/src/org/jetbrains/jet/plugin/conversion/copy/ConvertJavaCopyPastePostProcessor.kt b/idea/src/org/jetbrains/jet/plugin/conversion/copy/ConvertJavaCopyPastePostProcessor.kt index 68d9dee39fd..6cfe4e88350 100644 --- a/idea/src/org/jetbrains/jet/plugin/conversion/copy/ConvertJavaCopyPastePostProcessor.kt +++ b/idea/src/org/jetbrains/jet/plugin/conversion/copy/ConvertJavaCopyPastePostProcessor.kt @@ -49,9 +49,7 @@ public class ConvertJavaCopyPastePostProcessor() : CopyPastePostProcessor { - if (file !is PsiJavaFile) { - return listOf() - } + if (file !is PsiJavaFile) return listOf() val lightFile = PsiFileFactory.getInstance(file.getProject())!!.createFileFromText(file.getText()!!, file) return listOf(CopiedCode(lightFile as? PsiJavaFile, startOffsets, endOffsets)) @@ -61,36 +59,33 @@ public class ConvertJavaCopyPastePostProcessor() : CopyPastePostProcessor(), false) if (expressionAtOffset != null) { return expressionAtOffset diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionCache.kt b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionCache.kt new file mode 100644 index 00000000000..5af28367661 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionCache.kt @@ -0,0 +1,123 @@ +/* + * 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.plugin.debugger.evaluate + +import com.intellij.openapi.project.Project +import com.intellij.psi.util.CachedValuesManager +import com.intellij.psi.util.CachedValueProvider +import com.intellij.psi.util.PsiModificationTracker +import org.jetbrains.jet.lang.psi.JetCodeFragment +import com.intellij.debugger.SourcePosition +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl +import java.util.ArrayList +import com.intellij.openapi.components.ServiceManager +import org.jetbrains.org.objectweb.asm.Type +import com.intellij.util.containers.MultiMap +import org.jetbrains.jet.lang.types.JetType +import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.openapi.application.ApplicationManager +import org.jetbrains.jet.lang.psi.JetFile +import com.intellij.psi.JavaPsiFacade +import org.jetbrains.jet.lang.resolve.DescriptorUtils +import org.jetbrains.jet.lang.descriptors.ClassDescriptor +import org.jetbrains.jet.plugin.caches.resolve.JavaResolveExtension +import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaClassImpl +import org.jetbrains.jet.lang.resolve.java.JvmClassName +import org.jetbrains.jet.codegen.AsmUtil +import org.apache.log4j.Logger + +class KotlinEvaluateExpressionCache(val project: Project) { + + private val cachedCompiledData = CachedValuesManager.getManager(project).createCachedValue( + { + CachedValueProvider.Result>( + MultiMap.create(), PsiModificationTracker.MODIFICATION_COUNT) + }, false) + + class object { + private val LOG = Logger.getLogger(javaClass())!! + + fun getInstance(project: Project) = ServiceManager.getService(project, javaClass())!! + + fun getOrCreateCompiledData( + codeFragment: JetCodeFragment, + sourcePosition: SourcePosition, + evaluationContext: EvaluationContextImpl, + create: (JetCodeFragment, SourcePosition) -> CompiledDataDescriptor + ): CompiledDataDescriptor { + val evaluateExpressionCache = getInstance(codeFragment.getProject()) + + return synchronized(evaluateExpressionCache.cachedCompiledData) { + (): CompiledDataDescriptor -> + val cache = evaluateExpressionCache.cachedCompiledData.getValue()!! + val text = "${codeFragment.importsToString()}\n${codeFragment.getText()}" + + val answer = cache[text].firstOrNull { + it.sourcePosition == sourcePosition || evaluateExpressionCache.canBeEvaluatedInThisContext(it, evaluationContext) + } + if (answer != null) return@synchronized answer + + val newCompiledData = create(codeFragment, sourcePosition) + LOG.debug("Compile bytecode for ${codeFragment.getText()}") + + cache.putValue(text, newCompiledData) + return@synchronized newCompiledData + } + } + } + + private fun canBeEvaluatedInThisContext(compiledData: CompiledDataDescriptor, context: EvaluationContextImpl): Boolean { + return compiledData.parameters.all { (p): Boolean -> + val (name, jetType) = p + val value = context.getFrameProxy()?.getStackFrame()?.findLocalVariable(name, failIfNotFound = false) + if (value == null) return@all false + + val thisDescriptor = value.asmType.getClassDescriptor() + val superClassDescriptor = jetType.getConstructor().getDeclarationDescriptor() as? ClassDescriptor + return@all thisDescriptor != null && superClassDescriptor != null && DescriptorUtils.isSubclass(thisDescriptor, superClassDescriptor) + } + } + + private fun Type.getClassDescriptor(): ClassDescriptor? { + if (AsmUtil.isPrimitive(this)) return null + + val jvmName = JvmClassName.byInternalName(getInternalName()).getFqNameForClassNameWithoutDollars() + + val platformClasses = JavaToKotlinClassMap.getInstance().mapPlatformClass(jvmName) + if (platformClasses.notEmpty) return platformClasses.first() + + return ApplicationManager.getApplication()?.runReadAction { + val classes = JavaPsiFacade.getInstance(project).findClasses(jvmName.asString(), GlobalSearchScope.allScope(project)) + if (classes.isEmpty()) null else JavaResolveExtension[project].resolveClass(JavaClassImpl(classes.first())) + } + } + + data class CompiledDataDescriptor(val bytecodes: ByteArray, val sourcePosition: SourcePosition, val funName: String, val parameters: ParametersDescriptor) + + class ParametersDescriptor : Iterable> { + private val list = ArrayList>() + + fun add(name: String, jetType: JetType) { + list.add(name to jetType) + } + + fun getParameterNames() = list.map { it.first } + + override fun iterator() = list.iterator() + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt index b039b139d48..4ef6861a05d 100644 --- a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt +++ b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt @@ -43,35 +43,24 @@ import org.jetbrains.eval4j.jdi.asJdiValue import org.jetbrains.eval4j.jdi.makeInitialFrame import org.jetbrains.jet.lang.resolve.java.PackageClassUtils import org.jetbrains.jet.lang.resolve.name.FqName -import org.jetbrains.jet.lang.psi.JetPsiFactory import org.jetbrains.eval4j.jdi.asValue -import org.jetbrains.jet.plugin.refactoring.createTempCopy -import org.jetbrains.jet.plugin.refactoring.extractFunction.ExtractionData -import org.jetbrains.jet.plugin.refactoring.extractFunction.performAnalysis -import org.jetbrains.jet.plugin.refactoring.extractFunction.validate -import org.jetbrains.jet.plugin.refactoring.extractFunction.generateFunction import org.jetbrains.jet.lang.psi.JetNamedFunction -import com.intellij.psi.PsiFile import org.jetbrains.jet.codegen.ClassFileFactory -import org.jetbrains.jet.plugin.codeInsight.CodeInsightUtils import org.jetbrains.jet.OutputFileCollection import org.jetbrains.jet.plugin.caches.resolve.getAnalysisResults import org.jetbrains.jet.lang.psi.JetCodeFragment -import org.jetbrains.jet.lang.psi.JetImportList import org.jetbrains.jet.lang.psi.codeFragmentUtil.skipVisibilityCheck -import org.jetbrains.jet.lang.psi.JetExpression -import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.Status import com.intellij.openapi.diagnostic.Logger import org.jetbrains.jet.codegen.CompilationErrorHandler -import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult -import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.ErrorMessage import org.jetbrains.jet.lang.diagnostics.Severity import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages import com.sun.jdi.request.EventRequest import com.sun.jdi.ObjectReference import com.intellij.debugger.engine.SuspendContext -import org.jetbrains.jet.plugin.refactoring.extractFunction.ExtractionOptions -import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder +import org.jetbrains.jet.plugin.debugger.evaluate.KotlinEvaluateExpressionCache.* +import org.jetbrains.jet.lang.resolve.BindingContext +import com.sun.jdi.StackFrame +import com.sun.jdi.VirtualMachine object KotlinEvaluationBuilder: EvaluatorBuilder { override fun build(codeFragment: PsiElement, position: SourcePosition?): ExpressionEvaluator { @@ -98,52 +87,24 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, val sourcePosition: SourcePosition ) : Evaluator { override fun evaluate(context: EvaluationContextImpl): Any? { + var isCompiledDataFromCache = true try { - val extractedFunction = getFunctionForExtractedFragment(codeFragment, sourcePosition.getFile(), sourcePosition.getLine()) - if (extractedFunction == null) { - throw IllegalStateException("Code fragment cannot be extracted to function: ${sourcePosition.getFile().getText()}:${sourcePosition.getLine()},\ncodeFragment = ${codeFragment.getText()}") + val compiledData = KotlinEvaluateExpressionCache.getOrCreateCompiledData(codeFragment, sourcePosition, context) { + fragment, position -> + isCompiledDataFromCache = false + extractAndCompile(fragment, position) } - - val classFileFactory = createClassFileFactory(extractedFunction) - - // KT-4509 - val outputFiles = (classFileFactory : OutputFileCollection).asList().filter { it.relativePath != "$packageInternalName.class" } - if (outputFiles.size() != 1) exception("Expression compiles to more than one class file. Note that lambdas, classes and objects are unsupported yet. List of files: ${outputFiles.makeString(",")}") + val args = context.getArgumentsByNames(compiledData.parameters.getParameterNames()) + val result = runEval4j(context, compiledData, args) val virtualMachine = context.getDebugProcess().getVirtualMachineProxy().getVirtualMachine() - var resultValue: Value? = null - ClassReader(outputFiles.first().asByteArray()).accept(object : ClassVisitor(ASM5) { - override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor? { - if (name == extractedFunction.getName()) { - return object : MethodNode(Opcodes.ASM5, access, name, desc, signature, exceptions) { - override fun visitEnd() { - val value = interpreterLoop( - this, - makeInitialFrame(this, context.getArgumentsByNames(extractedFunction.getParameterNamesForDebugger())), - JDIEval(virtualMachine, - context.getClassLoader()!!, - context.getSuspendContext().getThread()?.getThreadReference()!!, context.getSuspendContext().getInvokePolicy()) - ) - - resultValue = when (value) { - is ValueReturned -> value.result - is ExceptionThrown -> exception(value.exception.toString()) - is AbnormalTermination -> exception(value.message) - else -> throw IllegalStateException("Unknown result value produced by eval4j") - } - } - } - } - return super.visitMethod(access, name, desc, signature, exceptions) - } - }, 0) - - if (resultValue == null) { - throw IllegalStateException("resultValue is null: cannot find method ${extractedFunction.getName()} in ${outputFiles.first().relativePath}") + // If bytecode was taken from cache and exception was thrown - recompile bytecode and run eval4j again + if (isCompiledDataFromCache && result is ExceptionThrown && result.kind == ExceptionThrown.ExceptionKind.BROKEN_CODE) { + return runEval4j(context, extractAndCompile(codeFragment, sourcePosition), args).toJdiValue(virtualMachine) } - return resultValue!!.asJdiValue(virtualMachine, resultValue!!.asmType) + return result.toJdiValue(virtualMachine) } catch(e: EvaluateException) { throw e @@ -159,85 +120,145 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, return null } - private fun SuspendContext.getInvokePolicy(): Int { - return if (getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD) ObjectReference.INVOKE_SINGLE_THREADED else 0 - } - - private fun JetNamedFunction.getParameterNamesForDebugger(): List { - val result = arrayListOf() - if (getReceiverTypeRef() != null) { - result.add("this") - } - for (param in getValueParameters()) { - result.add(param.getName()!!) - } - return result - } - - private fun EvaluationContextImpl.getArgumentsByNames(parameterNames: List): List { - val frames = getFrameProxy()?.getStackFrame() - if (frames != null) { - fun getValue(name: String): Value { - return try { - when (name) { - "this" -> frames.thisObject().asValue() - else -> frames.getValue(frames.visibleVariableByName(name)).asValue() - } - } - catch(e: Exception) { - exception("Cannot get parameter value from local variables table: parameterName = ${name}. Note that captured parameters are unsupported yet.") - } + class object { + private fun extractAndCompile(codeFragment: JetCodeFragment, sourcePosition: SourcePosition): CompiledDataDescriptor { + val extractedFunction = getFunctionForExtractedFragment(codeFragment, sourcePosition.getFile(), sourcePosition.getLine()) + if (extractedFunction == null) { + throw IllegalStateException("Code fragment cannot be extracted to function: ${sourcePosition.getFile().getText()}:${sourcePosition.getLine()},\ncodeFragment = ${codeFragment.getText()}") } - return parameterNames.map { getValue(it) } + val classFileFactory = createClassFileFactory(codeFragment, extractedFunction) + + // KT-4509 + val outputFiles = (classFileFactory : OutputFileCollection).asList().filter { it.relativePath != "$packageInternalName.class" } + if (outputFiles.size() != 1) exception("Expression compiles to more than one class file. Note that lambdas, classes and objects are unsupported yet. List of files: ${outputFiles.makeString(",")}") + + val funName = extractedFunction.getName() + if (funName == null) { + throw IllegalStateException("Extracted function should have a name: ${extractedFunction.getText()}") + } + return CompiledDataDescriptor(outputFiles.first().asByteArray(), sourcePosition, funName, extractedFunction.getParametersForDebugger()) } - return Collections.emptyList() - } - private fun createClassFileFactory(extractedFunction: JetNamedFunction): ClassFileFactory { - return ApplicationManager.getApplication()?.runReadAction(object: Computable { - override fun compute(): ClassFileFactory? { - val file = createFileForDebugger(codeFragment, extractedFunction) + private fun runEval4j( + context: EvaluationContextImpl, + compiledData: CompiledDataDescriptor, + args: List + ): InterpreterResult { + val virtualMachine = context.getDebugProcess().getVirtualMachineProxy().getVirtualMachine() - checkForSyntacticErrors(file) + var resultValue: InterpreterResult? = null + ClassReader(compiledData.bytecodes).accept(object : ClassVisitor(ASM5) { + override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor? { + if (name == compiledData.funName) { + return object : MethodNode(Opcodes.ASM5, access, name, desc, signature, exceptions) { + override fun visitEnd() { + resultValue = interpreterLoop( + this, + makeInitialFrame(this, args), + JDIEval(virtualMachine, + context.getClassLoader()!!, + context.getSuspendContext().getThread()?.getThreadReference()!!, + context.getSuspendContext().getInvokePolicy()) + ) + } + } + } - val analyzeExhaust = file.getAnalysisResults() - if (analyzeExhaust.isError()) { - exception(analyzeExhaust.getError()) + return super.visitMethod(access, name, desc, signature, exceptions) } + }, 0) - val bindingContext = analyzeExhaust.getBindingContext() - bindingContext.getDiagnostics().forEach { - diagnostic -> - if (diagnostic.getSeverity() == Severity.ERROR) { - exception(DefaultErrorMessages.RENDERER.render(diagnostic)) + return resultValue ?: throw IllegalStateException("resultValue is null: cannot find method ${compiledData.funName}") + } + + private fun InterpreterResult.toJdiValue(vm: VirtualMachine): com.sun.jdi.Value? { + val jdiValue = when (this) { + is ValueReturned -> result + is ExceptionThrown -> exception(exception.toString()) + is AbnormalTermination -> exception(message) + else -> throw IllegalStateException("Unknown result value produced by eval4j") + } + return jdiValue.asJdiValue(vm, jdiValue.asmType) + } + + private fun SuspendContext.getInvokePolicy(): Int { + return if (getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD) ObjectReference.INVOKE_SINGLE_THREADED else 0 + } + + private fun JetNamedFunction.getParametersForDebugger(): ParametersDescriptor { + return ApplicationManager.getApplication()?.runReadAction(Computable { + val parameters = ParametersDescriptor() + val bindingContext = getAnalysisResults().getBindingContext() + val descriptor = bindingContext[BindingContext.FUNCTION, this] + if (descriptor != null) { + val receiver = descriptor.getReceiverParameter() + if (receiver != null) { + parameters.add("this", receiver.getType()) + } + + descriptor.getValueParameters().forEach { + param -> + parameters.add(param.getName().asString(), param.getType()) } } - - val state = GenerationState( - file.getProject(), - ClassBuilderFactories.BINARIES, - analyzeExhaust.getModuleDescriptor(), - bindingContext, - listOf(file) - ) - - KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION) - - return state.getFactory() - } - })!! - - } - - private fun exception(msg: String) = throw EvaluateExceptionUtil.createEvaluateException(msg) - - private fun exception(e: Throwable) { - val message = e.getMessage() - if (message != null) { - exception(message) + parameters + })!! + } + + private fun EvaluationContextImpl.getArgumentsByNames(parameterNames: List): List { + val frames = getFrameProxy()?.getStackFrame() + if (frames != null) { + return parameterNames.map { frames.findLocalVariable(it)!! } + } + return Collections.emptyList() + } + + private fun createClassFileFactory(codeFragment: JetCodeFragment, extractedFunction: JetNamedFunction): ClassFileFactory { + return ApplicationManager.getApplication()?.runReadAction(object : Computable { + override fun compute(): ClassFileFactory? { + val file = createFileForDebugger(codeFragment, extractedFunction) + + checkForSyntacticErrors(file) + + val analyzeExhaust = file.getAnalysisResults() + if (analyzeExhaust.isError()) { + exception(analyzeExhaust.getError()) + } + + val bindingContext = analyzeExhaust.getBindingContext() + bindingContext.getDiagnostics().forEach { + diagnostic -> + if (diagnostic.getSeverity() == Severity.ERROR) { + exception(DefaultErrorMessages.RENDERER.render(diagnostic)) + } + } + + val state = GenerationState( + file.getProject(), + ClassBuilderFactories.BINARIES, + analyzeExhaust.getModuleDescriptor(), + bindingContext, + listOf(file) + ) + + KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION) + + return state.getFactory() + } + })!! + + } + + private fun exception(msg: String) = throw EvaluateExceptionUtil.createEvaluateException(msg) + + private fun exception(e: Throwable) { + val message = e.getMessage() + if (message != null) { + exception(message) + } + throw EvaluateExceptionUtil.createEvaluateException(e) } - throw EvaluateExceptionUtil.createEvaluateException(e) } } @@ -271,38 +292,6 @@ private fun createFileForDebugger(codeFragment: JetCodeFragment, return jetFile } -fun addImportsToFile(newImportList: JetImportList?, tmpFile: JetFile) { - if (newImportList != null) { - val tmpFileImportList = tmpFile.getImportList() - val packageDirective = tmpFile.getPackageDirective() - if (tmpFileImportList == null) { - tmpFile.addAfter(JetPsiFactory.createNewLine(tmpFile.getProject()), packageDirective) - tmpFile.addAfter(newImportList, tmpFile.getPackageDirective()) - } - else { - tmpFileImportList.replace(newImportList) - } - tmpFile.addAfter(JetPsiFactory.createNewLine(tmpFile.getProject()), packageDirective) - } -} - -fun addDebugExpressionBeforeContextElement(codeFragment: JetCodeFragment, contextElement: PsiElement): JetExpression? { - val parent = contextElement.getParent() - if (parent == null) return null - - parent.addBefore(JetPsiFactory.createNewLine(contextElement.getProject()), contextElement) - - val debugExpression = codeFragment.getContentElement() - if (debugExpression == null) return null - - val newDebugExpression = parent.addBefore(debugExpression, contextElement) - if (newDebugExpression == null) return null - - parent.addBefore(JetPsiFactory.createNewLine(contextElement.getProject()), contextElement) - - return newDebugExpression as JetExpression -} - fun checkForSyntacticErrors(file: JetFile) { try { AnalyzingUtils.checkForSyntacticErrors(file) @@ -312,69 +301,22 @@ fun checkForSyntacticErrors(file: JetFile) { } } -private fun getFunctionForExtractedFragment( - codeFragment: JetCodeFragment, - breakpointFile: PsiFile, - breakpointLine: Int -): JetNamedFunction? { - - fun getErrorMessageForExtractFunctionResult(analysisResult: AnalysisResult): String { - return analysisResult.messages.map { - errorMessage -> - val message = when(errorMessage) { - ErrorMessage.NO_EXPRESSION -> "Cannot perform an action without an expression" - ErrorMessage.NO_CONTAINER -> "Cannot perform an action at this breakpoint ${breakpointFile.getName()}:${breakpointLine}" - ErrorMessage.SUPER_CALL -> "Cannot perform an action for expression with super call" - ErrorMessage.DENOTABLE_TYPES -> "Cannot perform an action because following types are unavailable from debugger scope" - ErrorMessage.MULTIPLE_OUTPUT -> "Cannot perform an action because this code fragment changes more than one variable" - ErrorMessage.DECLARATIONS_OUT_OF_SCOPE, - ErrorMessage.OUTPUT_AND_EXIT_POINT, - ErrorMessage.MULTIPLE_EXIT_POINTS, - ErrorMessage.VARIABLES_ARE_USED_OUTSIDE -> "Cannot perform an action for this expression" - } - if (errorMessage.additionalInfo == null) message else "$message: ${errorMessage.additionalInfo?.makeString(", ")}" - }.makeString(", ") - } - - return ApplicationManager.getApplication()?.runReadAction(object: Computable { - override fun compute(): JetNamedFunction? { - checkForSyntacticErrors(codeFragment) - - val originalFile = breakpointFile as JetFile - - val lineStart = CodeInsightUtils.getStartLineOffset(originalFile, breakpointLine) - if (lineStart == null) return null - - val tmpFile = originalFile.createTempCopy { it } - tmpFile.skipVisibilityCheck = true - - val elementAtOffset = tmpFile.findElementAt(lineStart) - if (elementAtOffset == null) return null - - val contextElement: PsiElement = CodeInsightUtils.getTopmostElementAtOffset(elementAtOffset, lineStart) ?: elementAtOffset - - addImportsToFile(codeFragment.importsAsImportList(), tmpFile) - - val newDebugExpression = addDebugExpressionBeforeContextElement(codeFragment, contextElement) - if (newDebugExpression == null) return null - - val targetSibling = tmpFile.getDeclarations().firstOrNull() - if (targetSibling == null) return null - - val analysisResult = ExtractionData( - tmpFile, Collections.singletonList(newDebugExpression), targetSibling, ExtractionOptions(false) - ).performAnalysis() - if (analysisResult.status != Status.SUCCESS) { - throw EvaluateExceptionUtil.createEvaluateException(getErrorMessageForExtractFunctionResult(analysisResult)) - } - - val validationResult = analysisResult.descriptor!!.validate() - if (!validationResult.conflicts.isEmpty()) { - throw EvaluateExceptionUtil.createEvaluateException("Following declarations are unavailable in debug scope: ${validationResult.conflicts.keySet()?.map { it.getText() }?.makeString(",")}") - } - - return validationResult.descriptor.generateFunction(true) +fun StackFrame.findLocalVariable(name: String, failIfNotFound: Boolean = true): Value? { + return try { + when (name) { + "this" -> thisObject().asValue() + else -> getValue(visibleVariableByName(name)).asValue() } - }) + } + catch(e: Exception) { + if (failIfNotFound) { + throw EvaluateExceptionUtil.createEvaluateException( + "Cannot find local variable: name = ${name}. Note that captured variables are unsupported yet.") + } + else { + return null + } + } } + diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/extractFunctionForDebuggerUtil.kt b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/extractFunctionForDebuggerUtil.kt new file mode 100644 index 00000000000..a932c5024db --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/extractFunctionForDebuggerUtil.kt @@ -0,0 +1,139 @@ +/* + * 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.plugin.debugger.evaluate + +import org.jetbrains.jet.lang.psi.JetCodeFragment +import com.intellij.psi.PsiFile +import org.jetbrains.jet.lang.psi.JetNamedFunction +import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult +import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.ErrorMessage +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.util.Computable +import org.jetbrains.jet.lang.psi.JetFile +import org.jetbrains.jet.plugin.codeInsight.CodeInsightUtils +import org.jetbrains.jet.plugin.refactoring.createTempCopy +import org.jetbrains.jet.lang.psi.codeFragmentUtil.skipVisibilityCheck +import com.intellij.psi.PsiElement +import org.jetbrains.jet.plugin.refactoring.extractFunction.ExtractionData +import java.util.Collections +import org.jetbrains.jet.plugin.refactoring.extractFunction.performAnalysis +import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.Status +import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil +import org.jetbrains.jet.plugin.refactoring.extractFunction.validate +import org.jetbrains.jet.plugin.refactoring.extractFunction.generateFunction +import org.jetbrains.jet.lang.psi.JetImportList +import org.jetbrains.jet.lang.psi.JetPsiFactory +import org.jetbrains.jet.lang.psi.JetExpression +import org.jetbrains.jet.plugin.refactoring.extractFunction.ExtractionOptions + +fun getFunctionForExtractedFragment( + codeFragment: JetCodeFragment, + breakpointFile: PsiFile, + breakpointLine: Int +): JetNamedFunction? { + + fun getErrorMessageForExtractFunctionResult(analysisResult: AnalysisResult): String { + return analysisResult.messages.map { + errorMessage -> + val message = when(errorMessage) { + ErrorMessage.NO_EXPRESSION -> "Cannot perform an action without an expression" + ErrorMessage.NO_CONTAINER -> "Cannot perform an action at this breakpoint ${breakpointFile.getName()}:${breakpointLine}" + ErrorMessage.SUPER_CALL -> "Cannot perform an action for expression with super call" + ErrorMessage.DENOTABLE_TYPES -> "Cannot perform an action because following types are unavailable from debugger scope" + ErrorMessage.MULTIPLE_OUTPUT -> "Cannot perform an action because this code fragment changes more than one variable" + ErrorMessage.DECLARATIONS_OUT_OF_SCOPE, + ErrorMessage.OUTPUT_AND_EXIT_POINT, + ErrorMessage.MULTIPLE_EXIT_POINTS, + ErrorMessage.VARIABLES_ARE_USED_OUTSIDE -> "Cannot perform an action for this expression" + } + if (errorMessage.additionalInfo == null) message else "$message: ${errorMessage.additionalInfo?.makeString(", ")}" + }.makeString(", ") + } + + return ApplicationManager.getApplication()?.runReadAction(object: Computable { + override fun compute(): JetNamedFunction? { + checkForSyntacticErrors(codeFragment) + + val originalFile = breakpointFile as JetFile + + val lineStart = CodeInsightUtils.getStartLineOffset(originalFile, breakpointLine) + if (lineStart == null) return null + + val tmpFile = originalFile.createTempCopy { it } + tmpFile.skipVisibilityCheck = true + + val elementAtOffset = tmpFile.findElementAt(lineStart) + if (elementAtOffset == null) return null + + val contextElement: PsiElement = CodeInsightUtils.getTopmostElementAtOffset(elementAtOffset, lineStart) ?: elementAtOffset + + addImportsToFile(codeFragment.importsAsImportList(), tmpFile) + + val newDebugExpression = addDebugExpressionBeforeContextElement(codeFragment, contextElement) + if (newDebugExpression == null) return null + + val targetSibling = tmpFile.getDeclarations().firstOrNull() + if (targetSibling == null) return null + + val analysisResult = ExtractionData( + tmpFile, Collections.singletonList(newDebugExpression), targetSibling, ExtractionOptions(false) + ).performAnalysis() + if (analysisResult.status != Status.SUCCESS) { + throw EvaluateExceptionUtil.createEvaluateException(getErrorMessageForExtractFunctionResult(analysisResult)) + } + + val validationResult = analysisResult.descriptor!!.validate() + if (!validationResult.conflicts.isEmpty()) { + throw EvaluateExceptionUtil.createEvaluateException("Following declarations are unavailable in debug scope: ${validationResult.conflicts.keySet()?.map { it.getText() }?.makeString(",")}") + } + + return validationResult.descriptor.generateFunction(true) + } + }) +} + +private fun addImportsToFile(newImportList: JetImportList?, tmpFile: JetFile) { + if (newImportList != null) { + val tmpFileImportList = tmpFile.getImportList() + val packageDirective = tmpFile.getPackageDirective() + if (tmpFileImportList == null) { + tmpFile.addAfter(JetPsiFactory.createNewLine(tmpFile.getProject()), packageDirective) + tmpFile.addAfter(newImportList, tmpFile.getPackageDirective()) + } + else { + tmpFileImportList.replace(newImportList) + } + tmpFile.addAfter(JetPsiFactory.createNewLine(tmpFile.getProject()), packageDirective) + } +} + +private fun addDebugExpressionBeforeContextElement(codeFragment: JetCodeFragment, contextElement: PsiElement): JetExpression? { + val parent = contextElement.getParent() + if (parent == null) return null + + parent.addBefore(JetPsiFactory.createNewLine(contextElement.getProject()), contextElement) + + val debugExpression = codeFragment.getContentElement() + if (debugExpression == null) return null + + val newDebugExpression = parent.addBefore(debugExpression, contextElement) + if (newDebugExpression == null) return null + + parent.addBefore(JetPsiFactory.createNewLine(contextElement.getProject()), contextElement) + + return newDebugExpression as JetExpression +} diff --git a/idea/src/org/jetbrains/jet/plugin/editor/KotlinSmartEnterHandler.kt b/idea/src/org/jetbrains/jet/plugin/editor/KotlinSmartEnterHandler.kt new file mode 100644 index 00000000000..91a10eba4b0 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/KotlinSmartEnterHandler.kt @@ -0,0 +1,161 @@ +/* + * 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.plugin.editor + +import org.jetbrains.jet.plugin.editor.fixers.* +import com.intellij.lang.SmartEnterProcessorWithFixers +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiFile +import com.intellij.util.text.CharArrayUtil +import com.intellij.psi.codeStyle.CodeStyleSettingsManager +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiWhiteSpace +import org.jetbrains.jet.lang.psi.JetDeclaration +import org.jetbrains.jet.lang.psi.JetBlockExpression +import org.jetbrains.jet.lang.psi.JetExpression +import org.jetbrains.jet.lang.psi.JetDeclarationWithBody +import org.jetbrains.jet.lang.psi.JetIfExpression +import org.jetbrains.jet.lang.psi.JetForExpression +import org.jetbrains.jet.lang.psi.JetParameter +import org.jetbrains.jet.lang.psi.JetFunctionLiteral +import com.intellij.psi.tree.TokenSet +import org.jetbrains.jet.JetNodeTypes +import org.jetbrains.jet.lang.psi.JetLoopExpression + +public class KotlinSmartEnterHandler: SmartEnterProcessorWithFixers() { + { + addFixers( + KotlinIfConditionFixer(), + KotlinMissingIfBranchFixer(), + + KotlinWhileConditionFixer(), + KotlinForConditionFixer(), + KotlinMissingForOrWhileBodyFixer(), + + KotlinWhenSubjectCaretFixer(), + KotlinMissingWhenBodyFixer(), + + KotlinDoWhileFixer(), + + KotlinFunctionParametersFixer(), + KotlinFunctionDeclarationBodyFixer() + ) + + addEnterProcessors(KotlinPlainEnterProcessor()) + } + + override fun getStatementAtCaret(editor: Editor?, psiFile: PsiFile?): PsiElement? { + var atCaret = super.getStatementAtCaret(editor, psiFile) + + if (atCaret is PsiWhiteSpace) return null + + while (atCaret != null) { + when { + atCaret?.isJetStatement() == true -> return atCaret + atCaret?.getParent() is JetFunctionLiteral -> return atCaret + atCaret is JetDeclaration -> { + val declaration = atCaret!! + when { + declaration is JetParameter && !declaration.isInLambdaExpression() -> {/* proceed to function declaration */} + declaration.getParent() is JetForExpression -> {/* skip variable declaration in 'for' expression */} + else -> return atCaret + } + } + } + + atCaret = atCaret?.getParent() + } + + return null + } + + override fun moveCaretInsideBracesIfAny(editor: Editor, file: PsiFile) { + var caretOffset = editor.getCaretModel().getOffset() + val chars = editor.getDocument().getCharsSequence() + + if (CharArrayUtil.regionMatches(chars, caretOffset, "{}")) { + caretOffset += 2 + } + else { + if (CharArrayUtil.regionMatches(chars, caretOffset, "{\n}")) { + caretOffset += 3 + } + } + + caretOffset = CharArrayUtil.shiftBackward(chars, caretOffset - 1, " \t") + 1 + + if (CharArrayUtil.regionMatches(chars, caretOffset - "{}".length(), "{}") || + CharArrayUtil.regionMatches(chars, caretOffset - "{\n}".length(), "{\n}")) { + commit(editor) + val settings = CodeStyleSettingsManager.getSettings(file.getProject()) + val old = settings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE + settings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = false + val elt = PsiTreeUtil.getParentOfType(file.findElementAt(caretOffset - 1), javaClass()) + if (elt != null) { + reformat(elt) + } + settings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = old + editor.getCaretModel().moveToOffset(caretOffset - 1) + } + } + + public fun registerUnresolvedError(offset: Int) { + if (myFirstErrorOffset > offset) { + myFirstErrorOffset = offset + } + } + + private fun PsiElement.isJetStatement() = + getParent() is JetBlockExpression || (getParent()?.getNode()?.getElementType() in BRANCH_CONTAINERS) + + class KotlinPlainEnterProcessor : SmartEnterProcessorWithFixers.FixEnterProcessor() { + private fun getControlStatementBlock(caret: Int, element: PsiElement): JetExpression? { + when (element) { + is JetDeclarationWithBody -> return element.getBodyExpression() + is JetIfExpression -> { + if (element.getThen().isWithCaret(caret)) return element.getThen() + if (element.getElse().isWithCaret(caret)) return element.getElse() + } + is JetLoopExpression -> return element.getBody() + } + + return null + } + + override fun doEnter(atCaret: PsiElement, file: PsiFile?, editor: Editor, modified: Boolean): Boolean { + val block = getControlStatementBlock(editor.getCaretModel().getOffset(), atCaret) as? JetBlockExpression + if (block != null) { + val firstElement = block.getFirstChild()?.getNextSibling() + + val offset = if (firstElement != null) { + firstElement.getTextRange()!!.getStartOffset() - 1 + } else { + block.getTextRange()!!.getEndOffset() + } + + editor.getCaretModel().moveToOffset(offset) + } + + plainEnter(editor) + return true + } + } +} + +private val BRANCH_CONTAINERS = TokenSet.create(JetNodeTypes.THEN, JetNodeTypes.ELSE, JetNodeTypes.BODY) +private fun JetParameter.isInLambdaExpression() = this.getParent()?.getParent() is JetFunctionLiteral diff --git a/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinDoWhileFixer.kt b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinDoWhileFixer.kt new file mode 100644 index 00000000000..88bb92c6454 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinDoWhileFixer.kt @@ -0,0 +1,65 @@ +/* + * 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.plugin.editor.fixers + +import com.intellij.lang.SmartEnterProcessorWithFixers +import org.jetbrains.jet.plugin.editor.KotlinSmartEnterHandler +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiElement +import org.jetbrains.jet.lang.psi.JetDoWhileExpression +import org.jetbrains.jet.lang.psi.JetBlockExpression + +public class KotlinDoWhileFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) { + if (psiElement !is JetDoWhileExpression) return + + val doc = editor.getDocument() + val stmt = psiElement as JetDoWhileExpression + val start = stmt.range.start + val body = stmt.getBody() + + val whileKeyword = stmt.getWhileKeywordElement() + if (body == null) { + if (whileKeyword == null) { + doc.replaceString(start, start + "do".length(), "do {} while()") + } + else { + doc.insertString(start + "do".length(), "{}") + } + return + } + else if (whileKeyword != null && body !is JetBlockExpression && body.startLine(doc) > stmt.startLine(doc)) { + doc.insertString(start + "do".length(), "{") + doc.insertString(whileKeyword.range.start - 1, "}") + + return + } + + if (stmt.getCondition() == null) { + val lParen = stmt.getLeftParenthesis() + val rParen = stmt.getRightParenthesis() + + when { + whileKeyword == null -> doc.insertString(stmt.range.end, "while()") + lParen == null && rParen == null -> { + doc.replaceString(whileKeyword.range.start, whileKeyword.range.end, "while()") + } + lParen != null -> processor.registerUnresolvedError(lParen.range.end) + } + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinForConditionFixer.kt b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinForConditionFixer.kt new file mode 100644 index 00000000000..66cbfb34340 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinForConditionFixer.kt @@ -0,0 +1,31 @@ +/* + * 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.plugin.editor.fixers + +import org.jetbrains.jet.lang.psi.JetWhileExpression +import com.intellij.psi.PsiElement +import org.jetbrains.jet.lang.psi.JetForExpression + +public class KotlinForConditionFixer: MissingConditionFixer() { + override val keyword = "for" + override fun getElement(element: PsiElement?) = element as? JetForExpression + override fun getCondition(element: JetForExpression) = + element.getLoopRange() ?: element.getLoopParameter() ?: element.getMultiParameter() + override fun getLeftParenthesis(element: JetForExpression) = element.getLeftParenthesis() + override fun getRightParenthesis(element: JetForExpression) = element.getRightParenthesis() + override fun getBody(element: JetForExpression) = element.getBody() +} diff --git a/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinFunctionDeclarationBodyFixer.kt b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinFunctionDeclarationBodyFixer.kt new file mode 100644 index 00000000000..c6845d9c096 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinFunctionDeclarationBodyFixer.kt @@ -0,0 +1,54 @@ +/* + * 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.plugin.editor.fixers + +import com.intellij.lang.SmartEnterProcessorWithFixers +import com.intellij.openapi.editor.Editor +import org.jetbrains.jet.plugin.editor.KotlinSmartEnterHandler +import com.intellij.psi.PsiElement +import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.jet.lang.psi.JetDeclaration +import org.jetbrains.jet.lang.psi.JetFunction +import org.jetbrains.jet.lang.psi.JetClassOrObject +import org.jetbrains.jet.lang.psi.JetPsiUtil +import org.jetbrains.jet.lexer.JetTokens +import org.jetbrains.jet.lang.psi.JetNamedFunction + + +public class KotlinFunctionDeclarationBodyFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) { + if (psiElement !is JetNamedFunction) return + if (psiElement.getBodyExpression() != null|| psiElement.getEqualsToken() != null) return + + val parentDeclaration = PsiTreeUtil.getParentOfType(psiElement, javaClass()) + if (parentDeclaration is JetClassOrObject) { + if (JetPsiUtil.isTrait(parentDeclaration) || psiElement.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { + return + } + } + + val doc = editor.getDocument() + var endOffset = psiElement.range.end + + if (psiElement.getText()?.last() == ';') { + doc.deleteString(endOffset - 1, endOffset) + endOffset-- + } + + doc.insertString(endOffset, "{}") + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinFunctionParametersFixer.kt b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinFunctionParametersFixer.kt new file mode 100644 index 00000000000..a5a042715f9 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinFunctionParametersFixer.kt @@ -0,0 +1,51 @@ +/* + * 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.plugin.editor.fixers + +import com.intellij.lang.SmartEnterProcessorWithFixers +import com.intellij.psi.PsiElement +import org.jetbrains.jet.plugin.editor.KotlinSmartEnterHandler +import com.intellij.openapi.editor.Editor +import org.jetbrains.jet.lang.psi.JetNamedFunction + + +public class KotlinFunctionParametersFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) { + if (psiElement !is JetNamedFunction) return; + + val parameterList = psiElement.getValueParameterList() + if (parameterList == null) { + val identifier = psiElement.getNameIdentifier() + if (identifier == null) return + + // Insert () after name or after type parameters list when it placed after name + val offset = Math.max(identifier.range.end, psiElement.getTypeParameterList()?.range?.end ?: psiElement.range.start) + editor.getDocument().insertString(offset, "()") + processor.registerUnresolvedError(offset + 1) + } + else { + val rParen = parameterList.getLastChild() + if (rParen == null) return + + if (")" != rParen.getText()) { + val params = parameterList.getParameters() + val offset = if (params.isEmpty()) parameterList.range.start + 1 else params.last().range.end + editor.getDocument().insertString(offset, ")") + } + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinIfConditionFixer.kt b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinIfConditionFixer.kt new file mode 100644 index 00000000000..621476c3ce1 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinIfConditionFixer.kt @@ -0,0 +1,34 @@ +/* + * 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.plugin.editor.fixers + +import org.jetbrains.jet.plugin.editor.KotlinSmartEnterHandler +import com.intellij.lang.SmartEnterProcessorWithFixers +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiElement +import org.jetbrains.jet.lang.psi.JetIfExpression +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.openapi.util.TextRange + +public class KotlinIfConditionFixer : MissingConditionFixer() { + override val keyword = "if" + override fun getElement(element: PsiElement?) = element as? JetIfExpression + override fun getCondition(element: JetIfExpression) = element.getCondition() + override fun getLeftParenthesis(element: JetIfExpression) = element.getLeftParenthesis() + override fun getRightParenthesis(element: JetIfExpression) = element.getRightParenthesis() + override fun getBody(element: JetIfExpression) = element.getThen() +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinMissingForOrWhileBodyFixer.kt b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinMissingForOrWhileBodyFixer.kt new file mode 100644 index 00000000000..3a83be9147e --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinMissingForOrWhileBodyFixer.kt @@ -0,0 +1,50 @@ +/* + * 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.plugin.editor.fixers + +import com.intellij.lang.SmartEnterProcessorWithFixers +import org.jetbrains.jet.plugin.editor.KotlinSmartEnterHandler +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiElement +import org.jetbrains.jet.lang.psi.JetWhileExpression +import org.jetbrains.jet.lang.psi.JetBlockExpression +import org.jetbrains.jet.lang.psi.JetLoopExpression +import org.jetbrains.jet.lang.psi.JetForExpression + +public class KotlinMissingForOrWhileBodyFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, element: PsiElement) { + if (!(element is JetForExpression || element is JetWhileExpression)) return + val loopExpression = element as JetLoopExpression + + val doc = editor.getDocument() + + val body = loopExpression.getBody() + if (body is JetBlockExpression) return + + if (!loopExpression.isValidLoopCondition()) return + + if (body != null && body.startLine(doc) == loopExpression.startLine(doc)) return + + val rParen = loopExpression.getRightParenthesis() + if (rParen == null) return + + doc.insertString(rParen.range.end, "{}") + } + + fun JetLoopExpression.isValidLoopCondition() = getLeftParenthesis() != null && getRightParenthesis() != null +} + diff --git a/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinMissingIfBranchFixer.kt b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinMissingIfBranchFixer.kt new file mode 100644 index 00000000000..f346a69dec3 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinMissingIfBranchFixer.kt @@ -0,0 +1,66 @@ +/* + * 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.plugin.editor.fixers + +import com.intellij.lang.SmartEnterProcessorWithFixers +import org.jetbrains.jet.plugin.editor.KotlinSmartEnterHandler +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiElement +import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.jet.lang.psi.JetIfExpression +import org.jetbrains.jet.plugin.formatter.JetBlock +import org.jetbrains.jet.lang.psi.JetBlockExpression + +public class KotlinMissingIfBranchFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, element: PsiElement) { + if (element !is JetIfExpression) return + val ifExpression = element as JetIfExpression + + val document = editor.getDocument() + val elseBranch = ifExpression.getElse() + val elseKeyword = ifExpression.getElseKeyword() + + if (elseKeyword != null) { + if (elseBranch == null || elseBranch !is JetBlockExpression && elseBranch.startLine(editor.getDocument()) > elseKeyword.startLine(editor.getDocument())) { + document.insertString(elseKeyword.range.end, "{}") + return + } + } + + val thenBranch = ifExpression.getThen() + if (thenBranch is JetBlockExpression) return + + val rParen = ifExpression.getRightParenthesis() + if (rParen == null) return + + var transformingOneLiner = false + if (thenBranch != null && thenBranch.startLine(editor.getDocument()) == ifExpression.startLine(editor.getDocument())) { + if (ifExpression.getCondition() != null) return + transformingOneLiner = true + } + + val probablyNextStatementParsedAsThen = elseKeyword == null && elseBranch == null && !transformingOneLiner + + if (thenBranch == null || probablyNextStatementParsedAsThen) { + document.insertString(rParen.range.end, "{}") + } + else { + document.insertString(rParen.range.end, "{") + document.insertString(thenBranch.range.end + 1, "}") + } + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinMissingWhenBodyFixer.kt b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinMissingWhenBodyFixer.kt new file mode 100644 index 00000000000..d53672fa617 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinMissingWhenBodyFixer.kt @@ -0,0 +1,49 @@ +/* + * 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.plugin.editor.fixers + +import com.intellij.lang.SmartEnterProcessorWithFixers +import org.jetbrains.jet.plugin.editor.KotlinSmartEnterHandler +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiElement +import org.jetbrains.jet.lang.psi.JetWhenExpression + +public class KotlinMissingWhenBodyFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, element: PsiElement) { + if (element !is JetWhenExpression) return + val whenExpression = element as JetWhenExpression + + val doc = editor.getDocument() + + val openBrace = whenExpression.getOpenBrace() + val closeBrace = whenExpression.getCloseBrace() + + if (openBrace == null && closeBrace == null && whenExpression.getEntries().isEmpty()) { + val openBraceAfter = whenExpression.insertOpenBraceAfter() + if (openBraceAfter != null) { + doc.insertString(openBraceAfter.range.end, "{}") + } + } + } + + fun JetWhenExpression.insertOpenBraceAfter(): PsiElement? = when { + getRightParenthesis() != null -> getRightParenthesis() + getSubjectExpression() != null -> null + getLeftParenthesis() != null -> null + else -> getWhenKeywordElement() + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinWhenSubjectCaretFixer.kt b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinWhenSubjectCaretFixer.kt new file mode 100644 index 00000000000..3da11c84eec --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinWhenSubjectCaretFixer.kt @@ -0,0 +1,37 @@ +/* + * 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.plugin.editor.fixers + +import com.intellij.psi.PsiElement +import com.intellij.lang.SmartEnterProcessorWithFixers +import org.jetbrains.jet.plugin.editor.KotlinSmartEnterHandler +import com.intellij.openapi.editor.Editor +import org.jetbrains.jet.lang.psi.JetWhenExpression + +public class KotlinWhenSubjectCaretFixer : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, element: PsiElement) { + if (element !is JetWhenExpression) return + + val lParen = element.getLeftParenthesis() + val rParen = element.getRightParenthesis() + val subject = element.getSubjectExpression() + + if (subject == null && lParen != null && rParen != null) { + processor.registerUnresolvedError(lParen.range.end) + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinWhileConditionFixer.kt b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinWhileConditionFixer.kt new file mode 100644 index 00000000000..7cc68128117 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/fixers/KotlinWhileConditionFixer.kt @@ -0,0 +1,30 @@ +/* + * 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.plugin.editor.fixers + +import org.jetbrains.jet.lang.psi.JetIfExpression +import com.intellij.psi.PsiElement +import org.jetbrains.jet.lang.psi.JetWhileExpression + +public class KotlinWhileConditionFixer: MissingConditionFixer() { + override val keyword = "while" + override fun getElement(element: PsiElement?) = element as? JetWhileExpression + override fun getCondition(element: JetWhileExpression) = element.getCondition() + override fun getLeftParenthesis(element: JetWhileExpression) = element.getLeftParenthesis() + override fun getRightParenthesis(element: JetWhileExpression) = element.getRightParenthesis() + override fun getBody(element: JetWhileExpression) = element.getBody() +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/editor/fixers/MissingConditionFixer.kt b/idea/src/org/jetbrains/jet/plugin/editor/fixers/MissingConditionFixer.kt new file mode 100644 index 00000000000..5428f9bb235 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/fixers/MissingConditionFixer.kt @@ -0,0 +1,64 @@ +/* + * 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.plugin.editor.fixers + +import com.intellij.lang.SmartEnterProcessorWithFixers +import org.jetbrains.jet.plugin.editor.KotlinSmartEnterHandler +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiElement + +abstract class MissingConditionFixer() : SmartEnterProcessorWithFixers.Fixer() { + override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, element: PsiElement) { + val workElement = getElement(element) + if (workElement == null) return + + val doc = editor.getDocument() + val lParen = getLeftParenthesis(workElement) + val rParen = getRightParenthesis(workElement) + val condition = getCondition(workElement) + + if (condition == null) { + if (lParen == null || rParen == null) { + var stopOffset = doc.getLineEndOffset(doc.getLineNumber(workElement.range.start)) + val then = getBody(workElement) + if (then != null) { + stopOffset = Math.min(stopOffset, then.range.start) + } + + stopOffset = Math.min(stopOffset, workElement.range.end) + + doc.replaceString(workElement.range.start, stopOffset, "$keyword ()") + processor.registerUnresolvedError(workElement.range.start + "$keyword (".length()) + } + else { + processor.registerUnresolvedError(lParen.range.end) + } + } + else { + if (rParen == null) { + doc.insertString(condition.range.end, ")") + } + } + } + + abstract val keyword: String + abstract fun getElement(element: PsiElement?): T? + abstract fun getCondition(element: T): PsiElement? + abstract fun getLeftParenthesis(element: T): PsiElement? + abstract fun getRightParenthesis(element: T): PsiElement? + abstract fun getBody(element: T): PsiElement? +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/editor/fixers/fixersUtil.kt b/idea/src/org/jetbrains/jet/plugin/editor/fixers/fixersUtil.kt new file mode 100644 index 00000000000..7b95cb43fba --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/editor/fixers/fixersUtil.kt @@ -0,0 +1,28 @@ +/* + * 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.plugin.editor.fixers + +import com.intellij.psi.PsiElement +import com.intellij.openapi.util.TextRange +import com.intellij.openapi.editor.Document + +val PsiElement.range: TextRange get() = getTextRange()!! +val TextRange.start: Int get() = getStartOffset() +val TextRange.end: Int get() = getEndOffset() + +fun PsiElement.startLine(doc: Document): Int = doc.getLineNumber(range.start) +fun PsiElement?.isWithCaret(caret: Int) = this?.getTextRange()?.contains(caret) == true \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/formatter/kotlinSpacingRules.kt b/idea/src/org/jetbrains/jet/plugin/formatter/kotlinSpacingRules.kt index e08e70d500d..91bc1a754c6 100644 --- a/idea/src/org/jetbrains/jet/plugin/formatter/kotlinSpacingRules.kt +++ b/idea/src/org/jetbrains/jet/plugin/formatter/kotlinSpacingRules.kt @@ -259,6 +259,7 @@ fun createSpacingBuilder(settings: CodeStyleSettings): KotlinSpacingBuilder { afterInside(LBRACE, BLOCK).lineBreakInCode() beforeInside(RBRACE, CLASS_BODY).lineBreakInCode() beforeInside(RBRACE, BLOCK).lineBreakInCode() + beforeInside(RBRACE, WHEN).lineBreakInCode() between(RPAR, BODY).spaces(1) // if when entry has block, spacing after arrow should be set by lbrace rule diff --git a/idea/src/org/jetbrains/jet/plugin/intentions/attributeCallReplacements/ReplaceContainsIntention.kt b/idea/src/org/jetbrains/jet/plugin/intentions/attributeCallReplacements/ReplaceContainsIntention.kt index 00fd6a0167e..e44059121fe 100644 --- a/idea/src/org/jetbrains/jet/plugin/intentions/attributeCallReplacements/ReplaceContainsIntention.kt +++ b/idea/src/org/jetbrains/jet/plugin/intentions/attributeCallReplacements/ReplaceContainsIntention.kt @@ -35,7 +35,7 @@ public open class ReplaceContainsIntention : AttributeCallReplacementIntention(" val ret = call.resolved.getResultingDescriptor().getReturnType() ?: return intentionFailed(editor, "undefined.returntype") - if (!JetTypeChecker.INSTANCE.isSubtypeOf(ret, KotlinBuiltIns.getInstance().getBooleanType())) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(ret, KotlinBuiltIns.getInstance().getBooleanType())) { return intentionFailed(editor, "contains.returns.boolean") } diff --git a/idea/src/org/jetbrains/jet/plugin/parameterInfo/JetFunctionParameterInfoHandler.java b/idea/src/org/jetbrains/jet/plugin/parameterInfo/JetFunctionParameterInfoHandler.java index 08b53ebb4d2..c31950ace67 100644 --- a/idea/src/org/jetbrains/jet/plugin/parameterInfo/JetFunctionParameterInfoHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/parameterInfo/JetFunctionParameterInfoHandler.java @@ -327,7 +327,7 @@ public class JetFunctionParameterInfoHandler implements ParameterInfoHandlerWith if (argument.getArgumentExpression() != null) { JetType paramType = getActualParameterType(param); JetType exprType = bindingContext.get(BindingContext.EXPRESSION_TYPE, argument.getArgumentExpression()); - return exprType == null || JetTypeChecker.INSTANCE.isSubtypeOf(exprType, paramType); + return exprType == null || JetTypeChecker.DEFAULT.isSubtypeOf(exprType, paramType); } return false; diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionParametersFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionParametersFix.java index dd64bfbeff5..6a57910e7ed 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionParametersFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionParametersFix.java @@ -127,7 +127,7 @@ public class AddFunctionParametersFix extends ChangeFunctionSignatureFix { JetType argumentType = expression != null ? bindingContext.get(BindingContext.EXPRESSION_TYPE, expression) : null; JetType parameterType = parameters.get(i).getType(); - if (argumentType != null && !JetTypeChecker.INSTANCE.isSubtypeOf(argumentType, parameterType)) + if (argumentType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(argumentType, parameterType)) changeSignatureData.getParameters().get(i).setTypeText(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(argumentType)); } else { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionToSupertypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionToSupertypeFix.java index 816b583f2c0..aac9af29ccd 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionToSupertypeFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionToSupertypeFix.java @@ -76,10 +76,10 @@ public class AddFunctionToSupertypeFix extends JetHintAction { if (o1.equals(o2)) { return 0; } - if (JetTypeChecker.INSTANCE.isSubtypeOf(o1, o2)) { + if (JetTypeChecker.DEFAULT.isSubtypeOf(o1, o2)) { return -1; } - if (JetTypeChecker.INSTANCE.isSubtypeOf(o2, o1)) { + if (JetTypeChecker.DEFAULT.isSubtypeOf(o2, o1)) { return 1; } return o1.toString().compareTo(o2.toString()); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddNameToArgumentFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddNameToArgumentFix.java index 4a60dc9aefb..b8785740004 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddNameToArgumentFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddNameToArgumentFix.java @@ -76,7 +76,7 @@ public class AddNameToArgumentFix extends JetIntentionAction { for (ValueParameterDescriptor parameter: callableDescriptor.getValueParameters()) { String name = parameter.getName().asString(); if (usedParameters.contains(name)) continue; - if (type == null || JetTypeChecker.INSTANCE.isSubtypeOf(type, parameter.getType())) { + if (type == null || JetTypeChecker.DEFAULT.isSubtypeOf(type, parameter.getType())) { names.add(name); } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddWhenElseBranchFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddWhenElseBranchFix.java index bd43ce97664..276d3b51041 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddWhenElseBranchFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddWhenElseBranchFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * Copyright 2010-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,12 +55,12 @@ public class AddWhenElseBranchFix extends JetIntentionAction @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return super.isAvailable(project, editor, file) && element.getCloseBraceNode() != null; + return super.isAvailable(project, editor, file) && element.getCloseBrace() != null; } @Override public void invoke(@NotNull Project project, Editor editor, JetFile file) throws IncorrectOperationException { - PsiElement whenCloseBrace = element.getCloseBraceNode(); + PsiElement whenCloseBrace = element.getCloseBrace(); assert (whenCloseBrace != null) : "isAvailable should check if close brace exist"; JetWhenEntry entry = JetPsiFactory.createWhenEntry(project, ELSE_ENTRY_TEXT); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/CastExpressionFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/CastExpressionFix.java index 4390f5eff4f..5315f2f9a8b 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/CastExpressionFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/CastExpressionFix.java @@ -61,7 +61,7 @@ public class CastExpressionFix extends JetIntentionAction { if (!super.isAvailable(project, editor, file)) return false; BindingContext context = ResolvePackage.getBindingContext((JetFile) file); JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, element); - return expressionType != null && JetTypeChecker.INSTANCE.isSubtypeOf(type, expressionType); + return expressionType != null && JetTypeChecker.DEFAULT.isSubtypeOf(type, expressionType); } @Override diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionLiteralReturnTypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionLiteralReturnTypeFix.java index d72d5ef61fa..e850ebac514 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionLiteralReturnTypeFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionLiteralReturnTypeFix.java @@ -68,7 +68,7 @@ public class ChangeFunctionLiteralReturnTypeFix extends JetIntentionAction for (FunctionDescriptor overriddenFunction: descriptor.getOverriddenDescriptors()) { JetType overriddenFunctionType = overriddenFunction.getReturnType(); if (overriddenFunctionType == null) continue; - if (!JetTypeChecker.INSTANCE.isSubtypeOf(functionType, overriddenFunctionType)) { + if (!JetTypeChecker.DEFAULT.isSubtypeOf(functionType, overriddenFunctionType)) { overriddenMismatchingFunctions.add(overriddenFunction); } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionSignatureFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionSignatureFix.java index f5094022b7d..2be9908055b 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionSignatureFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionSignatureFix.java @@ -132,7 +132,7 @@ public abstract class ChangeFunctionSignatureFix extends JetIntentionAction ErrorUtils.containsErrorType(expectedType) }) { return array() } - val theType = TypeUtils.intersect(JetTypeChecker.INSTANCE, expectedTypes) + val theType = TypeUtils.intersect(JetTypeChecker.DEFAULT, expectedTypes) if (theType != null) { return array(theType) } @@ -494,8 +494,8 @@ private class JetTypeSubstitution(public val forType: JetType, public val byType private fun JetType.substitute(substitution: JetTypeSubstitution, variance: Variance): JetType { if (when (variance) { Variance.INVARIANT -> this == substitution.forType - Variance.IN_VARIANCE -> JetTypeChecker.INSTANCE.isSubtypeOf(this, substitution.forType) - Variance.OUT_VARIANCE -> JetTypeChecker.INSTANCE.isSubtypeOf(substitution.forType, this) + Variance.IN_VARIANCE -> JetTypeChecker.DEFAULT.isSubtypeOf(this, substitution.forType) + Variance.OUT_VARIANCE -> JetTypeChecker.DEFAULT.isSubtypeOf(substitution.forType, this) }) { return substitution.byType } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelper.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelper.java index 2c4fb190de5..66ea97590db 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelper.java @@ -43,12 +43,21 @@ public class ImportInsertHelper { * * @param importFqn full name of the import * @param file File where directive should be added. + * @param optimize Optimize existing imports before adding new one. */ - public static void addImportDirectiveIfNeeded(@NotNull FqName importFqn, @NotNull JetFile file) { - addImportDirectiveIfNeeded(new ImportPath(importFqn, false), file); + public static void addImportDirectiveIfNeeded(@NotNull FqName importFqn, @NotNull JetFile file, boolean optimize) { + addImportDirectiveIfNeeded(new ImportPath(importFqn, false), file, optimize); } - public static void addImportDirectiveOrChangeToFqName(@NotNull FqName importFqn, @NotNull JetFile file, int refOffset, @NotNull PsiElement targetElement) { + public static void addImportDirectiveIfNeeded(@NotNull FqName importFqn, @NotNull JetFile file) { + addImportDirectiveIfNeeded(importFqn, file, true); + } + + public static void addImportDirectiveOrChangeToFqName( + @NotNull FqName importFqn, + @NotNull JetFile file, + int refOffset, + @NotNull PsiElement targetElement) { PsiReference reference = file.findReferenceAt(refOffset); if (reference instanceof JetReference) { PsiElement target = reference.resolve(); @@ -80,12 +89,12 @@ public class ImportInsertHelper { return; } } - addImportDirectiveIfNeeded(new ImportPath(importFqn, false), file); + addImportDirectiveIfNeeded(importFqn, file); } - public static void addImportDirectiveIfNeeded(@NotNull ImportPath importPath, @NotNull JetFile file) { - if (CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) { - new OptimizeImportsProcessor(file.getProject(), file).runWithoutProgress(); + public static void addImportDirectiveIfNeeded(@NotNull ImportPath importPath, @NotNull JetFile file, boolean optimize) { + if (optimize) { + optimizeImportsIfNeeded(file); } if (!needImport(importPath, file)) { @@ -95,6 +104,16 @@ public class ImportInsertHelper { writeImportToFile(importPath, file); } + public static void optimizeImportsIfNeeded(JetFile file) { + if (CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) { + optimizeImports(file); + } + } + + public static void optimizeImports(JetFile file) { + new OptimizeImportsProcessor(file.getProject(), file).runWithoutProgress(); + } + public static void writeImportToFile(@NotNull ImportPath importPath, @NotNull JetFile file) { if (file instanceof JetCodeFragment) { JetImportDirective newDirective = JetPsiFactory.createImportDirective(file.getProject(), importPath); @@ -105,6 +124,7 @@ public class ImportInsertHelper { JetImportList importList = file.getImportList(); if (importList != null) { JetImportDirective newDirective = JetPsiFactory.createImportDirective(file.getProject(), importPath); + importList.add(JetPsiFactory.createNewLine(file.getProject())); importList.add(newDirective); } else { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java index cc9a9ff1f49..617ee4ef412 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java @@ -20,12 +20,12 @@ import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters2; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage; @@ -33,6 +33,7 @@ import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage; import java.util.LinkedList; import java.util.List; +//TODO: should use change signature to deal with cases of multiple overridden descriptors public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsFactory { @NotNull @Override @@ -71,9 +72,9 @@ public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsF ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, ((JetOperationExpression) expression).getOperationReference()); if (resolvedCall != null) { - PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getResultingDescriptor()); - if (declaration instanceof JetFunction) { - actions.add(new ChangeFunctionReturnTypeFix((JetFunction) declaration, expectedType)); + JetFunction declaration = getFunctionDeclaration(context, resolvedCall); + if (declaration != null) { + actions.add(new ChangeFunctionReturnTypeFix(declaration, expectedType)); } } } @@ -82,9 +83,9 @@ public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsF if (parentBinary.getRight() == expression) { ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, parentBinary.getOperationReference()); if (resolvedCall != null) { - PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getResultingDescriptor()); - if (declaration instanceof JetFunction) { - JetParameter binaryOperatorParameter = ((JetFunction) declaration).getValueParameterList().getParameters().get(0); + JetFunction declaration = getFunctionDeclaration(context, resolvedCall); + if (declaration != null) { + JetParameter binaryOperatorParameter = declaration.getValueParameterList().getParameters().get(0); actions.add(new ChangeParameterTypeFix(binaryOperatorParameter, expressionType)); } } @@ -96,9 +97,9 @@ public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsF ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, ((JetCallExpression) expression).getCalleeExpression()); if (resolvedCall != null) { - PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getResultingDescriptor()); - if (declaration instanceof JetFunction) { - actions.add(new ChangeFunctionReturnTypeFix((JetFunction) declaration, expectedType)); + JetFunction declaration = getFunctionDeclaration(context, resolvedCall); + if (declaration != null) { + actions.add(new ChangeFunctionReturnTypeFix(declaration, expectedType)); } } } @@ -128,4 +129,13 @@ public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsF } return actions; } + + @Nullable + private static JetFunction getFunctionDeclaration(@NotNull BindingContext context, @NotNull ResolvedCall resolvedCall) { + PsiElement result = QuickFixUtil.safeGetDeclaration(context, resolvedCall); + if (result instanceof JetFunction) { + return (JetFunction) result; + } + return null; + } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java index 5d8052847ad..65e26224f91 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java @@ -90,10 +90,10 @@ public class QuickFixUtil { if (overriddenReturnType == null) { return null; } - if (matchingReturnType == null || JetTypeChecker.INSTANCE.isSubtypeOf(overriddenReturnType, matchingReturnType)) { + if (matchingReturnType == null || JetTypeChecker.DEFAULT.isSubtypeOf(overriddenReturnType, matchingReturnType)) { matchingReturnType = overriddenReturnType; } - else if (!JetTypeChecker.INSTANCE.isSubtypeOf(matchingReturnType, overriddenReturnType)) { + else if (!JetTypeChecker.DEFAULT.isSubtypeOf(matchingReturnType, overriddenReturnType)) { return null; } } @@ -109,7 +109,7 @@ public class QuickFixUtil { BindingContext context = ResolvePackage.getBindingContext(callExpression.getContainingJetFile()); ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, callExpression.getCalleeExpression()); if (resolvedCall == null) return null; - PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getCandidateDescriptor()); + PsiElement declaration = safeGetDeclaration(context, resolvedCall); if (declaration instanceof JetFunction) { return ((JetFunction) declaration).getValueParameterList(); } @@ -119,6 +119,16 @@ public class QuickFixUtil { return null; } + @Nullable + public static PsiElement safeGetDeclaration(@NotNull BindingContext context, @NotNull ResolvedCall resolvedCall) { + List declarations = BindingContextUtils.descriptorToDeclarations(context, resolvedCall.getResultingDescriptor()); + //do not create fix if descriptor has more than one overridden declaration + if (declarations.size() == 1) { + return declarations.iterator().next(); + } + return null; + } + @Nullable public static JetParameter getParameterCorrespondingToFunctionLiteralPassedOutsideArgumentList(@NotNull JetFunctionLiteralExpression functionLiteralExpression) { if (!(functionLiteralExpression.getParent() instanceof JetCallExpression)) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/SpecifyTypeExplicitlyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/SpecifyTypeExplicitlyFix.java index 50f220f038b..350506570c2 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/SpecifyTypeExplicitlyFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/SpecifyTypeExplicitlyFix.java @@ -22,9 +22,11 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetNamedDeclaration; import org.jetbrains.jet.lang.psi.JetNamedFunction; import org.jetbrains.jet.lang.psi.JetProperty; +import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.JetBundle; @@ -40,7 +42,7 @@ public class SpecifyTypeExplicitlyFix extends PsiElementBaseIntentionAction { } @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiElement element) { //noinspection unchecked JetNamedDeclaration declaration = PsiTreeUtil.getParentOfType(element, JetProperty.class, JetNamedFunction.class); JetType type = getTypeForDeclaration(declaration); @@ -51,12 +53,12 @@ public class SpecifyTypeExplicitlyFix extends PsiElementBaseIntentionAction { addTypeAnnotation(project, editor, (JetNamedFunction) declaration, type); } else { - assert false : "Couldn't find property or function"; + assert false : "Couldn't find property or function " + JetPsiUtil.getElementTextWithContext((JetElement) element); } } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + public boolean isAvailable(@NotNull Project project, @NotNull Editor editor, @NotNull PsiElement element) { //noinspection unchecked JetNamedDeclaration declaration = PsiTreeUtil.getParentOfType(element, JetProperty.class, JetNamedFunction.class); if (declaration instanceof JetProperty) { @@ -66,7 +68,7 @@ public class SpecifyTypeExplicitlyFix extends PsiElementBaseIntentionAction { setText(JetBundle.message("specify.type.explicitly.add.return.type.action.name")); } else { - assert false : "Couldn't find property or function"; + assert false : "Couldn't find property or function " + JetPsiUtil.getElementTextWithContext((JetElement) element); } return !getTypeForDeclaration(declaration).isError(); diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/JetNameSuggester.java b/idea/src/org/jetbrains/jet/plugin/refactoring/JetNameSuggester.java index 24674e39958..a7efdec3eaa 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/JetNameSuggester.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/JetNameSuggester.java @@ -98,7 +98,7 @@ public class JetNameSuggester { private static void addNamesForType(ArrayList result, JetType jetType, JetNameValidator validator) { KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); - JetTypeChecker typeChecker = JetTypeChecker.INSTANCE; + JetTypeChecker typeChecker = JetTypeChecker.DEFAULT; jetType = TypeUtils.makeNotNullable(jetType); // wipe out '?' if (ErrorUtils.containsErrorType(jetType)) return; if (typeChecker.equalTypes(builtIns.getBooleanType(), jetType)) { diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringUtil.java b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringUtil.java index 2509d0e1c92..43af6fed9b4 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringUtil.java @@ -440,7 +440,7 @@ public class JetRefactoringUtil { BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement(expression); JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); if (expressionType == null || !(expressionType instanceof PackageType) && - !JetTypeChecker.INSTANCE.equalTypes(KotlinBuiltIns. + !JetTypeChecker.DEFAULT.equalTypes(KotlinBuiltIns. getInstance().getUnitType(), expressionType)) { expressions.add(expression); } diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractKotlinFunctionHandler.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractKotlinFunctionHandler.kt index 86c3240f65f..69a2419c3cd 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractKotlinFunctionHandler.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractKotlinFunctionHandler.kt @@ -59,7 +59,8 @@ public class ExtractKotlinFunctionHandler(public val allContainersEnabled: Boole editor: Editor, file: JetFile, elements: List, - targetSibling: PsiElement + targetSibling: PsiElement, + preprocessor: ((ExtractionDescriptor) -> Unit)? = null ) { val project = file.getProject() @@ -83,7 +84,7 @@ public class ExtractKotlinFunctionHandler(public val allContainersEnabled: Boole dialog.getCurrentDescriptor() } - + preprocessor?.invoke(descriptor) project.executeWriteCommand(EXTRACT_FUNCTION) { descriptor.generateFunction() } } diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionData.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionData.kt index c98a1cc68bd..a077d119d24 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionData.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionData.kt @@ -45,6 +45,12 @@ import org.jetbrains.jet.lang.psi.psiUtil.getParentByType import org.jetbrains.jet.lang.psi.JetDeclaration import org.jetbrains.jet.lang.psi.JetDeclarationWithBody import org.jetbrains.jet.lang.psi.JetUserType +import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall +import org.jetbrains.jet.lang.psi.JetParameter +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor +import org.jetbrains.jet.lang.psi.JetPsiFactory +import org.jetbrains.jet.lang.resolve.BindingContextUtils +import org.jetbrains.jet.lang.psi.JetFunctionLiteral data class ExtractionOptions(val inferUnitTypeForUnusedValues: Boolean) { class object { @@ -95,20 +101,31 @@ class ExtractionData( val originalStartOffset = originalElements.first?.let { e -> e.getTextRange()!!.getStartOffset() } + private val itFakeDeclaration by Delegates.lazy { JetPsiFactory.createParameter(project, "it", null) } + val refOffsetToDeclaration by Delegates.lazy { + fun isExtractableIt(descriptor: DeclarationDescriptor, context: BindingContext): Boolean { + if (!(descriptor is ValueParameterDescriptor && (context[BindingContext.AUTO_CREATED_IT, descriptor] ?: false))) return false + val function = BindingContextUtils.descriptorToDeclaration(context, descriptor.getContainingDeclaration()) as? JetFunctionLiteral + return function == null || !function.isInsideOf(originalElements) + } + if (originalStartOffset != null) { val resultMap = HashMap() + for ((ref, context) in JetFileReferencesResolver.resolve(originalFile, getExpressions())) { if (ref !is JetSimpleNameExpression) continue val resolvedCallKey = (ref.getParent() as? JetThisExpression) ?: ref - val resolvedCall = context[BindingContext.RESOLVED_CALL, resolvedCallKey] + val resolvedCall = context[BindingContext.RESOLVED_CALL, resolvedCallKey]?.let { + (it as? VariableAsFunctionResolvedCall)?.functionCall ?: it + } val descriptor = context[BindingContext.REFERENCE_TARGET, ref] if (descriptor == null) continue val declaration = DescriptorToDeclarationUtil.getDeclaration(project, descriptor, context) as? PsiNamedElement - if (declaration == null) continue + ?: if (isExtractableIt(descriptor, context)) itFakeDeclaration else continue val offset = ref.getTextRange()!!.getStartOffset() - originalStartOffset resultMap[offset] = ResolveResult(ref, declaration, descriptor, resolvedCall) diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionDescriptor.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionDescriptor.kt index c949d5451d6..8ea801675c4 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionDescriptor.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ExtractionDescriptor.kt @@ -31,19 +31,21 @@ import org.jetbrains.jet.lang.psi.psiUtil.replaced import org.jetbrains.jet.lang.psi.JetQualifiedExpression import org.jetbrains.jet.lang.psi.JetTypeParameter import org.jetbrains.jet.lang.psi.JetTypeConstraint -import kotlin.properties.Delegates import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.Status import org.jetbrains.jet.plugin.refactoring.JetRefactoringBundle import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.ErrorMessage -data class Parameter( - val argumentText: String, - val name: String, - var mirrorVarName: String?, - val parameterType: JetType, - val receiverCandidate: Boolean -) { +trait Parameter { + val argumentText: String + val name: String + val mirrorVarName: String? + val parameterType: JetType + val parameterTypeCandidates: List + val receiverCandidate: Boolean + val nameForRef: String get() = mirrorVarName ?: name + + fun copy(name: String, parameterType: JetType): Parameter } data class TypeParameter( @@ -165,7 +167,7 @@ class AnalysisResult ( fun renderMessage(): String { val message = JetRefactoringBundle.message(when(this) { - NO_EXPRESSION -> "cannot.refactor.no.expresson" + NO_EXPRESSION -> "cannot.refactor.no.expression" NO_CONTAINER -> "cannot.refactor.no.container" SUPER_CALL -> "cannot.extract.super.call" DENOTABLE_TYPES -> "parameter.types.are.not.denotable" diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt index eac0647d964..2d276e5abea 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/extractFunctionUtils.kt @@ -38,7 +38,6 @@ import org.jetbrains.jet.lang.psi.JetPsiFactory.FunctionBuilder import org.jetbrains.jet.plugin.refactoring.JetNameValidatorImpl import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil import org.jetbrains.jet.plugin.imports.canBeReferencedViaImport -import org.jetbrains.jet.lang.types.checker.JetTypeChecker import org.jetbrains.jet.lang.resolve.DescriptorUtils import com.intellij.psi.PsiNamedElement import org.jetbrains.jet.lang.descriptors.impl.LocalVariableDescriptor @@ -56,18 +55,16 @@ import org.jetbrains.jet.lang.diagnostics.Errors import org.jetbrains.jet.lang.psi.psiUtil.replaced import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.Status import org.jetbrains.jet.plugin.refactoring.extractFunction.AnalysisResult.ErrorMessage -import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.* import org.jetbrains.jet.lang.cfg.pseudocode.instructions.special.LocalFunctionDeclarationInstruction -import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.WriteValueInstruction -import org.jetbrains.jet.lang.cfg.pseudocode.instructions.Instruction -import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.CallInstruction -import org.jetbrains.jet.lang.cfg.pseudocode.instructions.JetElementInstruction -import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.OperationInstruction -import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.ReadValueInstruction 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.cfg.pseudocodeTraverser.getNextInstructions +import kotlin.properties.Delegates +import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.traverse +import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.TraversalOrder +import org.jetbrains.jet.lang.resolve.bindingContextUtil.getTargetFunctionDescriptor +import com.intellij.psi.PsiWhiteSpace +import org.jetbrains.jet.lang.resolve.OverridingUtil private val DEFAULT_FUNCTION_NAME = "myFun" private val DEFAULT_RETURN_TYPE = KotlinBuiltIns.getInstance().getUnitType() @@ -84,7 +81,10 @@ private fun List.getModifiedVarDescriptors(bindingContext: BindingC private fun List.getExitPoints(): List = filter { localInstruction -> localInstruction.nextInstructions.any { it !in this } } -private fun List.getResultType(bindingContext: BindingContext, options: ExtractionOptions): JetType { +private fun List.getResultType( + pseudocode: Pseudocode, + bindingContext: BindingContext, + options: ExtractionOptions): JetType { fun instructionToType(instruction: Instruction): JetType? { val expression = when (instruction) { is ReturnValueInstruction -> { @@ -101,10 +101,7 @@ private fun List.getResultType(bindingContext: BindingContext, opti } if (expression == null) return null - if (options.inferUnitTypeForUnusedValues) { - val pseudocode = firstOrNull()?.owner - if (pseudocode != null && expression.isStatement(pseudocode)) return null - } + if (options.inferUnitTypeForUnusedValues && expression.isStatement(pseudocode)) return null return bindingContext[BindingContext.EXPRESSION_TYPE, expression] } @@ -123,10 +120,17 @@ private fun JetType.isMeaningful(): Boolean { } private fun List.analyzeControlFlow( + pseudocode: Pseudocode, bindingContext: BindingContext, options: ExtractionOptions, parameters: Set ): Pair { + fun isCurrentFunctionReturn(expression: JetReturnExpression): Boolean { + val functionDescriptor = expression.getTargetFunctionDescriptor(bindingContext) + val currentDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, pseudocode.getCorrespondingElement()] + return currentDescriptor == functionDescriptor + } + val exitPoints = getExitPoints() val valuedReturnExits = ArrayList() @@ -135,19 +139,26 @@ private fun List.analyzeControlFlow( exitPoints.forEach { val e = (it as? UnconditionalJumpInstruction)?.element val insn = - if (e != null && e !is JetBreakExpression && e !is JetContinueExpression) { - it.previousInstructions.firstOrNull() + when { + it !is ReturnValueInstruction && it !is ReturnNoValueInstruction && it.owner != pseudocode -> + null + e != null && e !is JetBreakExpression && e !is JetContinueExpression -> + it.previousInstructions.firstOrNull() + else -> + it } - else it when (insn) { - is ReturnValueInstruction -> valuedReturnExits.add(insn) + is ReturnValueInstruction -> + if (isCurrentFunctionReturn(insn.element as JetReturnExpression)) { + valuedReturnExits.add(insn) + } is AbstractJumpInstruction -> { val element = insn.element - if (element is JetReturnExpression - || element is JetBreakExpression - || element is JetContinueExpression) { + if ((element is JetReturnExpression && isCurrentFunctionReturn(element)) + || element is JetBreakExpression + || element is JetContinueExpression) { jumpExits.add(insn) } else if (element !is JetThrowExpression) { @@ -161,8 +172,8 @@ private fun List.analyzeControlFlow( } } - val typeOfDefaultFlow = defaultExits.getResultType(bindingContext, options) - val returnValueType = valuedReturnExits.getResultType(bindingContext, options) + val typeOfDefaultFlow = defaultExits.getResultType(pseudocode, bindingContext, options) + val returnValueType = valuedReturnExits.getResultType(pseudocode, bindingContext, options) val defaultControlFlow = DefaultControlFlow(if (returnValueType.isMeaningful()) returnValueType else typeOfDefaultFlow) val outParameters = parameters.filterTo(HashSet()) { it.mirrorVarName != null } @@ -204,7 +215,7 @@ private fun List.analyzeControlFlow( } if (!valuedReturnExits.checkEquivalence(false)) return multipleExitsError - return Pair(ExpressionEvaluationWithCallSiteReturn(valuedReturnExits.getResultType(bindingContext, options)), null) + return Pair(ExpressionEvaluationWithCallSiteReturn(valuedReturnExits.getResultType(pseudocode, bindingContext, options)), null) } if (jumpExits.isNotEmpty()) { @@ -307,8 +318,51 @@ private fun JetType.processTypeIfExtractable( } } +private class MutableParameter( + override val argumentText: String, + override val name: String, + override val mirrorVarName: String?, + override val receiverCandidate: Boolean +): Parameter { + // All modifications happen in the same thread + private var writable: Boolean = true + private val defaultTypes = HashSet() + private val typePredicates = HashSet() + + fun addDefaultType(jetType: JetType) { + assert(writable, "Can't add type to non-writable parameter $name") + defaultTypes.add(jetType) + } + + fun addTypePredicate(predicate: TypePredicate) { + assert(writable, "Can't add type predicate to non-writable parameter $name") + typePredicates.add(predicate) + } + + override val parameterTypeCandidates: List by Delegates.lazy { + writable = false + listOf(parameterType) + TypeUtils.getAllSupertypes(parameterType).filter(and(typePredicates)) + } + + override val parameterType: JetType by Delegates.lazy { + writable = false + CommonSupertypes.commonSupertype(defaultTypes) + } + + override fun copy(name: String, parameterType: JetType): Parameter = DelegatingParameter(this, name, parameterType) +} + +private class DelegatingParameter( + val original: Parameter, + override val name: String, + override val parameterType: JetType +): Parameter by original { + override fun copy(name: String, parameterType: JetType): Parameter = DelegatingParameter(original, name, parameterType) +} + private fun ExtractionData.inferParametersInfo( commonParent: PsiElement, + pseudocode: Pseudocode, localInstructions: List, bindingContext: BindingContext, replacementMap: MutableMap, @@ -323,7 +377,9 @@ private fun ExtractionData.inferParametersInfo( ) val modifiedVarDescriptors = localInstructions.getModifiedVarDescriptors(bindingContext) - val extractedDescriptorToParameter = HashMap() + val extractedDescriptorToParameter = HashMap() + + val valueUsageMap = pseudocode.collectValueUsages() for (refInfo in getBrokenReferencesInfo(createTemporaryCodeBlock())) { val (originalRef, originalDeclaration, originalDescriptor, resolvedCall) = refInfo.resolveResult @@ -379,64 +435,42 @@ private fun ExtractionData.inferParametersInfo( val extractParameter = extractThis || extractLocalVar if (extractParameter) { - val parameterType = - if (hasThisReceiver) { - when (descriptorToExtract) { - is ClassDescriptor -> descriptorToExtract.getDefaultType() - is CallableDescriptor -> descriptorToExtract.getReceiverParameter()?.getType() - else -> null - } ?: DEFAULT_PARAMETER_TYPE - } - else bindingContext[BindingContext.EXPRESSION_TYPE, originalRef] ?: DEFAULT_PARAMETER_TYPE + val parameterType = when { + receiver.exists() -> receiver.getType() + else -> bindingContext[BindingContext.AUTOCAST, originalRef] + ?: bindingContext[BindingContext.EXPRESSION_TYPE, originalRef] + ?: DEFAULT_PARAMETER_TYPE + } if (!parameterType.processTypeIfExtractable(bindingContext, typeParameters, nonDenotableTypes)) continue - val existingParameter = extractedDescriptorToParameter[descriptorToExtract] - val parameter: Parameter = - if (existingParameter != null) { - if (!JetTypeChecker.INSTANCE.equalTypes(existingParameter.parameterType, parameterType)) { - val newParameter = existingParameter.copy( - parameterType = CommonSupertypes.commonSupertype(listOf(existingParameter.parameterType, parameterType)) - ) + val parameterTypePredicate = + pseudocode.getElementValue(originalRef)?.let { getExpectedTypePredicate(it, valueUsageMap, bindingContext) } ?: AllTypes - extractedDescriptorToParameter[descriptorToExtract] = newParameter - - for ((offset, replacement) in replacementMap) { - if (replacement is ParameterReplacement && replacement.parameter == existingParameter) { - replacementMap[offset] = replacement.copy(newParameter) - } - } - - newParameter + val parameter = extractedDescriptorToParameter.getOrPut(descriptorToExtract) { + val parameterName = + if (extractThis) { + JetNameSuggester.suggestNames(parameterType, varNameValidator, null).first() } - else existingParameter - } - else { - val parameterName = - if (extractThis) { - JetNameSuggester.suggestNames(parameterType, varNameValidator, null).first() - } - else originalDeclaration.getName()!! + else originalDeclaration.getName()!! - val mirrorVarName = if (descriptorToExtract in modifiedVarDescriptors) - varNameValidator.validateName(parameterName)!! - else null + val mirrorVarName = + if (descriptorToExtract in modifiedVarDescriptors) varNameValidator.validateName(parameterName)!! else null - val argumentText = - if (hasThisReceiver && extractThis) - "this@${parameterType.getConstructor().getDeclarationDescriptor()!!.getName().asString()}" - else - (thisExpr ?: ref).getText() ?: throw AssertionError("'this' reference shouldn't be empty: code fragment = ${getCodeFragmentText()}") + val argumentText = + if (hasThisReceiver && extractThis) + "this@${parameterType.getConstructor().getDeclarationDescriptor()!!.getName().asString()}" + else + (thisExpr ?: ref).getText() ?: throw AssertionError("'this' reference shouldn't be empty: code fragment = ${getCodeFragmentText()}") - val parameter = Parameter(argumentText, parameterName, mirrorVarName, parameterType, extractThis) + MutableParameter(argumentText, parameterName, mirrorVarName, extractThis) + } - extractedDescriptorToParameter[descriptorToExtract] = parameter - - parameter - } + parameter.addDefaultType(parameterType) + parameter.addTypePredicate(parameterTypePredicate) replacementMap[refInfo.offsetInBody] = - if (hasThisReceiver && extractThis) AddPrefixReplacement(parameter) else RenameReplacement(parameter) + if (hasThisReceiver && extractThis) AddPrefixReplacement(parameter) else RenameReplacement(parameter) } } } @@ -451,20 +485,20 @@ private fun ExtractionData.inferParametersInfo( } private fun ExtractionData.checkLocalDeclarationsWithNonLocalUsages( - allInstructions: List, + pseudocode: Pseudocode, localInstructions: List, bindingContext: BindingContext ): ErrorMessage? { // todo: non-locally used declaration can be turned into the output value val declarations = ArrayList() - for (instruction in allInstructions) { - if (instruction in localInstructions) continue - - PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, bindingContext)?.let { descriptor -> - val declaration = DescriptorToDeclarationUtil.getDeclaration(project, descriptor, bindingContext) - if (declaration is JetNamedDeclaration && declaration.isInsideOf(originalElements)) { - declarations.add(declaration) + pseudocode.traverse(TraversalOrder.FORWARD) { instruction -> + if (instruction !in localInstructions) { + PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, bindingContext)?.let { descriptor -> + val declaration = DescriptorToDeclarationUtil.getDeclaration(project, descriptor, bindingContext) + if (declaration is JetNamedDeclaration && declaration.isInsideOf(originalElements)) { + declarations.add(declaration) + } } } } @@ -500,6 +534,16 @@ private fun ExtractionData.checkDeclarationsMovingOutOfScope(controlFlow: Contro return null } +private fun ExtractionData.getLocalInstructions(pseudocode: Pseudocode): List { + val instructions = ArrayList() + pseudocode.traverse(TraversalOrder.FORWARD) { + if (it is JetElementInstruction && it.element.isInsideOf(originalElements)) { + instructions.add(it) + } + } + return instructions +} + fun ExtractionData.performAnalysis(): AnalysisResult { if (originalElements.empty) { return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(ErrorMessage.NO_EXPRESSION)) @@ -516,16 +560,14 @@ fun ExtractionData.performAnalysis(): AnalysisResult { val bindingContext = resolveSession.resolveToElement(enclosingDeclaration.getBodyExpression()) val pseudocode = PseudocodeUtil.generatePseudocode(enclosingDeclaration, bindingContext) - val localInstructions = pseudocode.getInstructions().filter { - it is JetElementInstruction && it.element.isInsideOf(originalElements) - } + val localInstructions = getLocalInstructions(pseudocode) val replacementMap = HashMap() val parameters = HashSet() val typeParameters = HashSet() val nonDenotableTypes = HashSet() val parameterError = inferParametersInfo( - commonParent, localInstructions, bindingContext, replacementMap, parameters, typeParameters, nonDenotableTypes + commonParent, pseudocode, localInstructions, bindingContext, replacementMap, parameters, typeParameters, nonDenotableTypes ) if (parameterError != null) { return AnalysisResult(null, Status.CRITICAL_ERROR, listOf(parameterError)) @@ -533,7 +575,7 @@ fun ExtractionData.performAnalysis(): AnalysisResult { val messages = ArrayList() - val (controlFlow, controlFlowMessage) = localInstructions.analyzeControlFlow(bindingContext, options, parameters) + val (controlFlow, controlFlowMessage) = localInstructions.analyzeControlFlow(pseudocode, bindingContext, options, parameters) controlFlowMessage?.let { messages.add(it) } controlFlow.returnType.processTypeIfExtractable(bindingContext, typeParameters, nonDenotableTypes) @@ -547,7 +589,7 @@ fun ExtractionData.performAnalysis(): AnalysisResult { ) } - checkLocalDeclarationsWithNonLocalUsages(pseudocode.getInstructions(), localInstructions, bindingContext)?.let { messages.add(it) } + checkLocalDeclarationsWithNonLocalUsages(pseudocode, localInstructions, bindingContext)?.let { messages.add(it) } checkDeclarationsMovingOutOfScope(controlFlow)?.let { messages.add(it) } val functionNameValidator = @@ -607,7 +649,7 @@ fun ExtractionDescriptor.validate(): ExtractionDescriptorWithConflicts { if (diagnostics.any { it.getFactory() == Errors.UNRESOLVED_REFERENCE } || (currentDescriptor != null && !ErrorUtils.isError(currentDescriptor) - && !compareDescriptors(currentDescriptor, resolveResult.descriptor))) { + && !comparePossiblyOverridingDescriptors(currentDescriptor, resolveResult.descriptor))) { conflicts.putValue( currentRefExpr, JetRefactoringBundle.message( @@ -632,6 +674,15 @@ fun ExtractionDescriptor.validate(): ExtractionDescriptorWithConflicts { return ExtractionDescriptorWithConflicts(this, conflicts) } +private fun comparePossiblyOverridingDescriptors(currentDescriptor: DeclarationDescriptor?, originalDescriptor: DeclarationDescriptor?): Boolean { + if (compareDescriptors(currentDescriptor, originalDescriptor)) return true + if (originalDescriptor is CallableDescriptor) { + if (!OverridingUtil.traverseOverridenDescriptors(originalDescriptor) { !compareDescriptors(currentDescriptor, it) }) return true + } + + return false +} + fun ExtractionDescriptor.getFunctionText( withBody: Boolean = true, descriptorRenderer: DescriptorRenderer = DescriptorRenderer.FQ_NAMES_IN_TYPES @@ -795,6 +846,27 @@ fun ExtractionDescriptor.generateFunction( } } + fun insertCall(anchor: PsiElement, wrappedCall: JetExpression) { + val firstExpression = extractionData.getExpressions().firstOrNull() + val enclosingCall = firstExpression?.getParent() as? JetCallExpression + if (enclosingCall == null || firstExpression !in enclosingCall.getFunctionLiteralArguments()) { + anchor.replace(wrappedCall) + return + } + + val argumentListExt = JetPsiFactory.createCallArguments(project, "(${wrappedCall.getText()})") + val argumentList = enclosingCall.getValueArgumentList() + if (argumentList == null) { + (anchor.getPrevSibling() as? PsiWhiteSpace)?.let { it.delete() } + anchor.replace(argumentListExt) + return + } + + val newArgText = (argumentList.getArguments() + argumentListExt.getArguments()).map { it.getText() }.joinToString(", ", "(", ")") + argumentList.replace(JetPsiFactory.createCallArguments(project, newArgText)) + anchor.delete() + } + fun makeCall(function: JetNamedFunction): JetNamedFunction { val anchor = extractionData.originalElements.first if (anchor == null) return function @@ -808,7 +880,7 @@ fun ExtractionDescriptor.generateFunction( val callText = parameters .map { it.argumentText } - .makeString(separator = ", ", prefix = "$name(", postfix = ")") + .joinToString(separator = ", ", prefix = "$name(", postfix = ")") val wrappedCall = when (controlFlow) { is ExpressionEvaluationWithCallSiteReturn -> JetPsiFactory.createReturn(project, callText) @@ -833,7 +905,7 @@ fun ExtractionDescriptor.generateFunction( else -> JetPsiFactory.createExpression(project, callText) } - anchor.replace(wrappedCall) + insertCall(anchor, wrappedCall) return function } diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ui/KotlinExtractFunctionDialog.java b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ui/KotlinExtractFunctionDialog.java index e5df89c5e73..26b599ac49d 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ui/KotlinExtractFunctionDialog.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ui/KotlinExtractFunctionDialog.java @@ -63,7 +63,7 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { setModal(true); setTitle(JetRefactoringBundle.message("extract.function")); init(); - update(false); + update(); } private void createUIComponents() { @@ -94,10 +94,8 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { return true; } - private void update(boolean recreateDescriptor) { - if (recreateDescriptor) { - this.currentDescriptor = createDescriptor(); - } + private void update() { + this.currentDescriptor = createDescriptor(); setOKActionEnabled(checkNames()); signaturePreviewField.setText( @@ -116,7 +114,7 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { new DocumentAdapter() { @Override public void documentChanged(DocumentEvent event) { - update(true); + update(); } } ); @@ -130,7 +128,7 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { new ItemListener() { @Override public void itemStateChanged(@NotNull ItemEvent e) { - update(true); + update(); } } ); @@ -138,7 +136,7 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { parameterTablePanel = new KotlinParameterTablePanel() { @Override protected void updateSignature() { - KotlinExtractFunctionDialog.this.update(true); + KotlinExtractFunctionDialog.this.update(); } @Override diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ui/KotlinParameterTablePanel.java b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ui/KotlinParameterTablePanel.java index 119c3cb47f2..72416c626b0 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ui/KotlinParameterTablePanel.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/extractFunction/ui/KotlinParameterTablePanel.java @@ -19,18 +19,25 @@ package org.jetbrains.jet.plugin.refactoring.extractFunction.ui; import com.intellij.ui.BooleanTableCellRenderer; import com.intellij.ui.TableUtil; import com.intellij.ui.ToolbarDecorator; +import com.intellij.ui.components.JBComboBoxLabel; +import com.intellij.ui.components.editors.JBComboBoxTableCellEditorComponent; import com.intellij.ui.table.JBTable; +import com.intellij.util.Function; +import com.intellij.util.ui.AbstractTableCellEditor; import com.intellij.util.ui.EditableModel; import kotlin.Function1; import kotlin.KotlinPackage; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.refactoring.JetNameSuggester; import org.jetbrains.jet.plugin.refactoring.extractFunction.Parameter; import org.jetbrains.jet.renderer.DescriptorRenderer; import javax.swing.*; import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellEditor; import javax.swing.table.TableColumn; import java.awt.*; @@ -42,11 +49,13 @@ public class KotlinParameterTablePanel extends JPanel { public static class ParameterInfo { private final Parameter originalParameter; private String name; + private JetType type; private boolean enabled = true; public ParameterInfo(Parameter originalParameter) { this.originalParameter = originalParameter; this.name = originalParameter.getName(); + this.type = originalParameter.getParameterType(); } public Parameter getOriginalParameter() { @@ -69,18 +78,16 @@ public class KotlinParameterTablePanel extends JPanel { this.name = name; } - public String getTypeAsString() { - return DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(getOriginalParameter().getParameterType()); + public JetType getType() { + return type; + } + + public void setType(JetType type) { + this.type = type; } public Parameter toParameter() { - return new Parameter( - originalParameter.getArgumentText(), - name, - originalParameter.getMirrorVarName(), - originalParameter.getParameterType(), - originalParameter.getReceiverCandidate() - ); + return originalParameter.copy(name, type); } } @@ -111,6 +118,7 @@ public class KotlinParameterTablePanel extends JPanel { myTable.setTableHeader(null); myTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + myTable.setCellSelectionEnabled(true); TableColumn checkBoxColumn = myTable.getColumnModel().getColumn(MyTableModel.CHECKMARK_COLUMN); TableUtil.setupCheckboxColumn(checkBoxColumn); @@ -128,6 +136,55 @@ public class KotlinParameterTablePanel extends JPanel { } ); + myTable.getColumnModel().getColumn(MyTableModel.PARAMETER_TYPE_COLUMN).setCellRenderer(new DefaultTableCellRenderer() { + private final JBComboBoxLabel myLabel = new JBComboBoxLabel(); + + @Override + @NotNull + public Component getTableCellRendererComponent( + @NotNull JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column + ) { + myLabel.setText(String.valueOf(value)); + myLabel.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); + myLabel.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground()); + if (isSelected) { + myLabel.setSelectionIcon(); + } else { + myLabel.setRegularIcon(); + } + return myLabel; + } + }); + + myTable.getColumnModel().getColumn(MyTableModel.PARAMETER_TYPE_COLUMN).setCellEditor(new AbstractTableCellEditor() { + final JBComboBoxTableCellEditorComponent myEditorComponent = new JBComboBoxTableCellEditorComponent(); + + @Override + @Nullable + public Object getCellEditorValue() { + return myEditorComponent.getEditorValue(); + } + + @Override + public Component getTableCellEditorComponent( + JTable table, Object value, boolean isSelected, int row, int column + ) { + ParameterInfo info = parameterInfos.get(row); + + myEditorComponent.setCell(table, row, column); + myEditorComponent.setOptions(info.getOriginalParameter().getParameterTypeCandidates().toArray()); + myEditorComponent.setDefaultValue(info.getType()); + myEditorComponent.setToString(new Function() { + @Override + public String fun(Object o) { + return DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType((JetType) o); + } + }); + + return myEditorComponent; + } + }); + myTable.setPreferredScrollableViewportSize(new Dimension(250, myTable.getRowHeight() * 5)); myTable.setShowGrid(false); myTable.setIntercellSpacing(new Dimension(0, 0)); @@ -159,20 +216,6 @@ public class KotlinParameterTablePanel extends JPanel { } }); - // F2: edit parameter name - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), "edit_parameter_name"); - actionMap.put("edit_parameter_name", new AbstractAction() { - @Override - public void actionPerformed(@NotNull ActionEvent e) { - if (!myTable.isEditing()) { - int row = myTable.getSelectedRow(); - if (row >= 0 && row < myTableModel.getRowCount()) { - TableUtil.editCellAt(myTable, row, MyTableModel.PARAMETER_NAME_COLUMN); - } - } - } - }); - // make ENTER work when the table has focus inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "invoke_impl"); actionMap.put("invoke_impl", new AbstractAction() { @@ -266,32 +309,29 @@ public class KotlinParameterTablePanel extends JPanel { @Override public Object getValueAt(int rowIndex, int columnIndex) { switch (columnIndex) { - case CHECKMARK_COLUMN: { + case CHECKMARK_COLUMN: return parameterInfos.get(rowIndex).isEnabled(); - } - case PARAMETER_NAME_COLUMN: { + case PARAMETER_NAME_COLUMN: return parameterInfos.get(rowIndex).getName(); - } - case PARAMETER_TYPE_COLUMN: { - return parameterInfos.get(rowIndex).getTypeAsString(); - } + case PARAMETER_TYPE_COLUMN: + return parameterInfos.get(rowIndex).getType(); + default: + return null; } - assert false; - return null; } @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + ParameterInfo info = parameterInfos.get(rowIndex); switch (columnIndex) { case CHECKMARK_COLUMN: { - parameterInfos.get(rowIndex).setEnabled((Boolean) aValue); + info.setEnabled((Boolean) aValue); fireTableRowsUpdated(rowIndex, rowIndex); myTable.getSelectionModel().setSelectionInterval(rowIndex, rowIndex); updateSignature(); break; } case PARAMETER_NAME_COLUMN: { - ParameterInfo info = parameterInfos.get(rowIndex); String name = (String) aValue; if (JetNameSuggester.isIdentifier(name)) { info.setName(name); @@ -299,16 +339,24 @@ public class KotlinParameterTablePanel extends JPanel { updateSignature(); break; } + case PARAMETER_TYPE_COLUMN: { + info.setType((JetType) aValue); + updateSignature(); + break; + } } } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { + ParameterInfo info = parameterInfos.get(rowIndex); switch (columnIndex) { case CHECKMARK_COLUMN: return isEnabled(); case PARAMETER_NAME_COLUMN: - return isEnabled() && parameterInfos.get(rowIndex).isEnabled(); + return isEnabled() && info.isEnabled(); + case PARAMETER_TYPE_COLUMN: + return isEnabled() && info.isEnabled() && info.getOriginalParameter().getParameterTypeCandidates().size() > 1; default: return false; } diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.java b/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.java index 4050baea7c2..422ec0d83c3 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.java @@ -31,11 +31,8 @@ import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; -import kotlin.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.analyzer.AnalyzerPackage; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -139,7 +136,7 @@ public class KotlinIntroduceVariableHandler extends KotlinIntroduceHandlerBase { JetType typeNoExpectedType = AnalyzerPackage.computeTypeInfoInContext( expression, scope, bindingTrace, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE, resolveSession.getModuleDescriptor() ).getType(); - if (expressionType != null && typeNoExpectedType != null && !JetTypeChecker.INSTANCE.equalTypes(expressionType, + if (expressionType != null && typeNoExpectedType != null && !JetTypeChecker.DEFAULT.equalTypes(expressionType, typeNoExpectedType)) { noTypeInference = true; } @@ -149,7 +146,7 @@ public class KotlinIntroduceVariableHandler extends KotlinIntroduceHandlerBase { return; } if (expressionType != null && - JetTypeChecker.INSTANCE.equalTypes(KotlinBuiltIns.getInstance().getUnitType(), expressionType)) { + JetTypeChecker.DEFAULT.equalTypes(KotlinBuiltIns.getInstance().getUnitType(), expressionType)) { showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.expression.has.unit.type")); return; } diff --git a/idea/testData/checker/FunctionReturnTypes.kt b/idea/testData/checker/FunctionReturnTypes.kt index f10d48a1d5d..6ec18678986 100644 --- a/idea/testData/checker/FunctionReturnTypes.kt +++ b/idea/testData/checker/FunctionReturnTypes.kt @@ -48,7 +48,7 @@ fun blockAndAndMismatch1() : Int { return true && false } fun blockAndAndMismatch2() : Int { - (return true) && (return false) + (return true) && (return false) } fun blockAndAndMismatch3() : Int { @@ -58,7 +58,7 @@ fun blockAndAndMismatch4() : Int { return true || false } fun blockAndAndMismatch5() : Int { - (return true) || (return false) + (return true) || (return false) } fun blockReturnValueTypeMatch1() : Int { return if (1 > 2) 1.0 else 2.0 diff --git a/idea/testData/checker/UnreachableCode.kt b/idea/testData/checker/UnreachableCode.kt index a98db2ae881..1f1c1c5245b 100644 --- a/idea/testData/checker/UnreachableCode.kt +++ b/idea/testData/checker/UnreachableCode.kt @@ -126,17 +126,17 @@ fun t8() : Int { } fun blockAndAndMismatch() : Boolean { - (return true) || (return false) + (return true) || (return false) return true } fun tf() : Int { - try {return 1} finally{return 1} + try {return 1} finally{return 1} return 1 } fun failtest(a : Int) : Int { - if (fail() || true) { + if (fail() || true) { } return 1 diff --git a/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/bar/Bar.java b/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/bar/Bar.java new file mode 100644 index 00000000000..44d04659de6 --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/bar/Bar.java @@ -0,0 +1,5 @@ +package bar; + +public interface Bar { + +} diff --git a/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/bar/Other.java b/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/bar/Other.java new file mode 100644 index 00000000000..4cc642287e9 --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/bar/Other.java @@ -0,0 +1,5 @@ +package bar; + +public interface Other { + +} diff --git a/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/foo/Foo.java b/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/foo/Foo.java new file mode 100644 index 00000000000..42b96fd46d6 --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/foo/Foo.java @@ -0,0 +1,9 @@ +package foo; + +import bar.Bar; +import bar.Other; +import java.util.ArrayList; + +public class Foo { + abstract public Bar foo(ArrayList list, Other other); +} diff --git a/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/foo/Impl.kt b/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/foo/Impl.kt new file mode 100644 index 00000000000..7e84873434b --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/foo/Impl.kt @@ -0,0 +1,7 @@ +package foo + +class Impl: Foo() { + +} + +// KT-4732 Override/Implement action does not add all imports when "Optimize imports on the fly" is enabled diff --git a/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/foo/Impl.kt.after b/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/foo/Impl.kt.after new file mode 100644 index 00000000000..d97d2fb4a0f --- /dev/null +++ b/idea/testData/codeInsight/overrideImplement/checkNotImportedTypesFromJava/foo/Impl.kt.after @@ -0,0 +1,14 @@ +package foo + +import java.util.ArrayList +import bar.Other +import bar.Bar + +class Impl: Foo() { + + override fun foo(list: ArrayList?, other: Other?): Bar? { + throw UnsupportedOperationException() + } +} + +// KT-4732 Override/Implement action does not add all imports when "Optimize imports on the fly" is enabled diff --git a/idea/testData/codeInsight/overrideImplement/functionFromTraitInJava/foo/JavaClass.java.after b/idea/testData/codeInsight/overrideImplement/functionFromTraitInJava/foo/JavaClass.java.after index af636c63cdf..650939d3544 100644 --- a/idea/testData/codeInsight/overrideImplement/functionFromTraitInJava/foo/JavaClass.java.after +++ b/idea/testData/codeInsight/overrideImplement/functionFromTraitInJava/foo/JavaClass.java.after @@ -1,11 +1,9 @@ package foo; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; class JavaClass { - @NotNull @Override public void bar(@Nullable String price) { diff --git a/idea/testData/debugger/tinyApp/outs/abstractFunCall.out b/idea/testData/debugger/tinyApp/outs/abstractFunCall.out index 4ec5a230c95..eef77767d00 100644 --- a/idea/testData/debugger/tinyApp/outs/abstractFunCall.out +++ b/idea/testData/debugger/tinyApp/outs/abstractFunCall.out @@ -2,6 +2,7 @@ LineBreakpoint created at abstractFunCall.kt:5 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! abstractFunCall.AbstractFunCallPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' abstractFunCall.kt:4 +Compile bytecode for (1 as java.lang.Number).intValue() Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/allFilesPresentInEvaluate.out b/idea/testData/debugger/tinyApp/outs/allFilesPresentInMultipleBreakpoints.out similarity index 100% rename from idea/testData/debugger/tinyApp/outs/allFilesPresentInEvaluate.out rename to idea/testData/debugger/tinyApp/outs/allFilesPresentInMultipleBreakpoints.out diff --git a/idea/testData/debugger/tinyApp/outs/allFilesPresentInSingleBreakpoint.out b/idea/testData/debugger/tinyApp/outs/allFilesPresentInSingleBreakpoint.out new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/testData/debugger/tinyApp/outs/arrays.out b/idea/testData/debugger/tinyApp/outs/arrays.out index f523f93f485..3f35b7c44b9 100644 --- a/idea/testData/debugger/tinyApp/outs/arrays.out +++ b/idea/testData/debugger/tinyApp/outs/arrays.out @@ -2,6 +2,15 @@ LineBreakpoint created at arrays.kt:5 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! arrays.ArraysPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' arrays.kt:4 +Compile bytecode for array(1, 2).map { it.toString() } +Compile bytecode for array(1, 2, 101, 102).filter { it > 100 } +Compile bytecode for array(1, 2).none() +Compile bytecode for array(1, 2).count() +Compile bytecode for array(1, 2).size +Compile bytecode for array(1, 2).first() +Compile bytecode for array(1, 2).last() +Compile bytecode for intArray(1, 2).max() +Compile bytecode for array(1, 2).max() Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/classFromAnotherPackage.out b/idea/testData/debugger/tinyApp/outs/classFromAnotherPackage.out index e1153240cae..6dbcb1bcad4 100644 --- a/idea/testData/debugger/tinyApp/outs/classFromAnotherPackage.out +++ b/idea/testData/debugger/tinyApp/outs/classFromAnotherPackage.out @@ -2,6 +2,8 @@ LineBreakpoint created at classFromAnotherPackage.kt:7 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! classFromAnotherPackage.ClassFromAnotherPackagePackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' classFromAnotherPackage.kt:6 +Compile bytecode for MyJavaClass() +Compile bytecode for stepInto.MyJavaClass() Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/classObjectVal.out b/idea/testData/debugger/tinyApp/outs/classObjectVal.out index 67eb6a81afc..a347b06cd23 100644 --- a/idea/testData/debugger/tinyApp/outs/classObjectVal.out +++ b/idea/testData/debugger/tinyApp/outs/classObjectVal.out @@ -2,6 +2,8 @@ LineBreakpoint created at classObjectVal.kt:10 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! classObjectVal.ClassObjectValPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' classObjectVal.kt:9 +Compile bytecode for coProp +Compile bytecode for MyClass.coProp Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/clearCache.out b/idea/testData/debugger/tinyApp/outs/clearCache.out new file mode 100644 index 00000000000..1ea2db70d4c --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/clearCache.out @@ -0,0 +1,52 @@ +LineBreakpoint created at clearCache.kt:12 +LineBreakpoint created at clearCache.kt:20 +LineBreakpoint created at clearCache.kt:31 +LineBreakpoint created at clearCache.kt:42 +LineBreakpoint created at clearCache.kt:52 +LineBreakpoint created at clearCache.kt:60 +LineBreakpoint created at clearCache.kt:78 +LineBreakpoint created at clearCache.kt:86 +LineBreakpoint created at clearCache.kt:95 +LineBreakpoint created at clearCache.kt:105 +LineBreakpoint created at clearCache.kt:113 +LineBreakpoint created at clearCache.kt:123 +LineBreakpoint created at clearCache.kt:131 +LineBreakpoint created at clearCache.kt:149 +LineBreakpoint created at clearCache.kt:154 +LineBreakpoint created at clearCache.kt:161 +LineBreakpoint created at clearCache.kt:169 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! clearCache.ClearCachePackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +clearCache.kt:11 +Compile bytecode for a +clearCache.kt:19 +Compile bytecode for a +clearCache.kt:30 +Compile bytecode for i +clearCache.kt:30 +clearCache.kt:41 +Compile bytecode for i +clearCache.kt:41 +clearCache.kt:51 +Compile bytecode for o.test() +clearCache.kt:59 +clearCache.kt:77 +Compile bytecode for c.size() +clearCache.kt:85 +clearCache.kt:94 +clearCache.kt:104 +clearCache.kt:112 +Compile bytecode for c.size() +clearCache.kt:122 +Compile bytecode for o.test() +clearCache.kt:130 +clearCache.kt:148 +Compile bytecode for obj.test() +clearCache.kt:153 +clearCache.kt:160 +Compile bytecode for o.test() +clearCache.kt:168 +Compile bytecode for o.test() +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/collections.out b/idea/testData/debugger/tinyApp/outs/collections.out index 618a4970607..8215589597b 100644 --- a/idea/testData/debugger/tinyApp/outs/collections.out +++ b/idea/testData/debugger/tinyApp/outs/collections.out @@ -2,6 +2,17 @@ LineBreakpoint created at collections.kt:6 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! collections.CollectionsPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' collections.kt:5 +Compile bytecode for arrayListOf(1, 2).map { it.toString() } +Compile bytecode for arrayListOf(1, 2, 101, 102).filter { it > 100 } +Compile bytecode for arrayListOf(1, 2).max() +Compile bytecode for arrayListOf(1, 2).count() +Compile bytecode for arrayListOf(1, 2).size +Compile bytecode for arrayListOf(1, 2).drop(1) +Compile bytecode for ar.map { if (it > 50) "big" else "small" } + .filter { it == "small" } + .size + +// RESULT: 2: I Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/dependentOnFile.out b/idea/testData/debugger/tinyApp/outs/dependentOnFile.out index 32f5a09bbfc..33361887a66 100644 --- a/idea/testData/debugger/tinyApp/outs/dependentOnFile.out +++ b/idea/testData/debugger/tinyApp/outs/dependentOnFile.out @@ -2,6 +2,14 @@ LineBreakpoint created at dependentOnFile.kt:5 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! dependentOnFile.DependentOnFilePackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' dependentOnFile.kt:4 +Compile bytecode for TestClass().testFun() +Compile bytecode for testFun() +Compile bytecode for TestObject.p +Compile bytecode for TestClass.p +Compile bytecode for 1.testExtFun() +Compile bytecode for testVal +Compile bytecode for 1.testExtVal +Compile bytecode for testDelVal Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/doubles.out b/idea/testData/debugger/tinyApp/outs/doubles.out new file mode 100644 index 00000000000..9028781bd0b --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/doubles.out @@ -0,0 +1,8 @@ +LineBreakpoint created at doubles.kt:7 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! doubles.DoublesPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +doubles.kt:6 +Compile bytecode for d1 + d2 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/enums.out b/idea/testData/debugger/tinyApp/outs/enums.out index 1c98f3af07a..9c475e903b1 100644 --- a/idea/testData/debugger/tinyApp/outs/enums.out +++ b/idea/testData/debugger/tinyApp/outs/enums.out @@ -2,6 +2,7 @@ LineBreakpoint created at enums.kt:7 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! enums.EnumsPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' enums.kt:6 +Compile bytecode for A == MyEnum.A Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/exceptions.out b/idea/testData/debugger/tinyApp/outs/exceptions.out new file mode 100644 index 00000000000..2491cf5912d --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/exceptions.out @@ -0,0 +1,20 @@ +LineBreakpoint created at exceptions.kt:9 +LineBreakpoint created at exceptions.kt:14 +LineBreakpoint created at exceptions.kt:26 +LineBreakpoint created at exceptions.kt:31 +LineBreakpoint created at exceptions.kt:42 +LineBreakpoint created at exceptions.kt:51 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! exceptions.ExceptionsPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +exceptions.kt:8 +Compile bytecode for fail() +exceptions.kt:13 +exceptions.kt:25 +Compile bytecode for o as Derived +exceptions.kt:30 +exceptions.kt:41 +Compile bytecode for c.get(0) +exceptions.kt:50 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/extractLocalVariables.out b/idea/testData/debugger/tinyApp/outs/extractLocalVariables.out index fca8952e6a5..e8c4407ba13 100644 --- a/idea/testData/debugger/tinyApp/outs/extractLocalVariables.out +++ b/idea/testData/debugger/tinyApp/outs/extractLocalVariables.out @@ -2,6 +2,10 @@ LineBreakpoint created at extractLocalVariables.kt:7 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! extractLocalVariables.ExtractLocalVariablesPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' extractLocalVariables.kt:6 +Compile bytecode for a +Compile bytecode for klass.f1(1) +Compile bytecode for args.size +Compile bytecode for klass.b Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/extractThis.out b/idea/testData/debugger/tinyApp/outs/extractThis.out index f308e1f8a66..fdbf81651b5 100644 --- a/idea/testData/debugger/tinyApp/outs/extractThis.out +++ b/idea/testData/debugger/tinyApp/outs/extractThis.out @@ -2,6 +2,9 @@ LineBreakpoint created at extractThis.kt:13 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! extractThis.ExtractThisPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' extractThis.kt:12 +Compile bytecode for prop +Compile bytecode for this.prop +Compile bytecode for prop + a Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/extractVariablesFromCall.out b/idea/testData/debugger/tinyApp/outs/extractVariablesFromCall.out index ac9998a6ba8..77392f6796a 100644 --- a/idea/testData/debugger/tinyApp/outs/extractVariablesFromCall.out +++ b/idea/testData/debugger/tinyApp/outs/extractVariablesFromCall.out @@ -2,6 +2,10 @@ LineBreakpoint created at extractVariablesFromCall.kt:8 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! extractVariablesFromCall.ExtractVariablesFromCallPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' extractVariablesFromCall.kt:7 +Compile bytecode for f1(a, s) +Compile bytecode for a.f2(s) +Compile bytecode for a f2 s +Compile bytecode for klass.f1(a, s) Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/imports.out b/idea/testData/debugger/tinyApp/outs/imports.out index 41c860627fb..f5d2f0980ef 100644 --- a/idea/testData/debugger/tinyApp/outs/imports.out +++ b/idea/testData/debugger/tinyApp/outs/imports.out @@ -2,6 +2,10 @@ LineBreakpoint created at imports.kt:10 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! imports.ImportsPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' imports.kt:9 +Compile bytecode for Collections.emptyList() +Compile bytecode for ArrayList() +Compile bytecode for HashSet() +Compile bytecode for JHashMap() Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/insertInBlock.out b/idea/testData/debugger/tinyApp/outs/insertInBlock.out index 6936cb0ff92..88697b9114e 100644 --- a/idea/testData/debugger/tinyApp/outs/insertInBlock.out +++ b/idea/testData/debugger/tinyApp/outs/insertInBlock.out @@ -2,6 +2,7 @@ LineBreakpoint created at insertInBlock.kt:6 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! insertInBlock.InsertInBlockPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' insertInBlock.kt:5 +Compile bytecode for 1 + 1 Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/multilineExpressionAtBreakpoint.out b/idea/testData/debugger/tinyApp/outs/multilineExpressionAtBreakpoint.out index 03b028c046d..0393ae05b63 100644 --- a/idea/testData/debugger/tinyApp/outs/multilineExpressionAtBreakpoint.out +++ b/idea/testData/debugger/tinyApp/outs/multilineExpressionAtBreakpoint.out @@ -2,6 +2,7 @@ LineBreakpoint created at multilineExpressionAtBreakpoint.kt:5 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! multilineExpressionAtBreakpoint.MultilineExpressionAtBreakpointPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' multilineExpressionAtBreakpoint.kt:4 +Compile bytecode for 1 + 1 Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/privateMember.out b/idea/testData/debugger/tinyApp/outs/privateMember.out index beb563cb681..94b8493961c 100644 --- a/idea/testData/debugger/tinyApp/outs/privateMember.out +++ b/idea/testData/debugger/tinyApp/outs/privateMember.out @@ -1,7 +1,13 @@ -LineBreakpoint created at privateMember.kt:5 +LineBreakpoint created at privateMember.kt:9 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! privateMember.PrivateMemberPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' -privateMember.kt:4 +privateMember.kt:8 +Compile bytecode for MyClass().privateFun() +Compile bytecode for MyClass().privateVal +Compile bytecode for MyClass.PrivateClass().a +Compile bytecode for base.privateFun() +Compile bytecode for derived.privateFun() +Compile bytecode for derivedAsBase.privateFun() Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/protectedMember.out b/idea/testData/debugger/tinyApp/outs/protectedMember.out index 9d9b6c38da6..35f56ba3f9f 100644 --- a/idea/testData/debugger/tinyApp/outs/protectedMember.out +++ b/idea/testData/debugger/tinyApp/outs/protectedMember.out @@ -2,6 +2,9 @@ LineBreakpoint created at protectedMember.kt:5 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! protectedMember.ProtectedMemberPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' protectedMember.kt:4 +Compile bytecode for MyClass().protectedFun() +Compile bytecode for MyClass().protectedVal +Compile bytecode for MyClass.ProtectedClass().a Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/simple.out b/idea/testData/debugger/tinyApp/outs/simple.out index caf68a7723d..a50f76d0ce6 100644 --- a/idea/testData/debugger/tinyApp/outs/simple.out +++ b/idea/testData/debugger/tinyApp/outs/simple.out @@ -2,6 +2,13 @@ LineBreakpoint created at simple.kt:5 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! simple.SimplePackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' simple.kt:4 +Compile bytecode for 1 +Compile bytecode for 1 + 1 +Compile bytecode for val a = 1 +a + args.size + +// RESULT: 1: I + Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/stdlib.out b/idea/testData/debugger/tinyApp/outs/stdlib.out index 08dcedff6bc..dd798d2101e 100644 --- a/idea/testData/debugger/tinyApp/outs/stdlib.out +++ b/idea/testData/debugger/tinyApp/outs/stdlib.out @@ -2,6 +2,13 @@ LineBreakpoint created at stdlib.kt:5 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! stdlib.StdlibPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' stdlib.kt:4 +Compile bytecode for array(100, 101) +Compile bytecode for array("a", "b", "c") +Compile bytecode for intArray(1, 2) +Compile bytecode for javaClass() +Compile bytecode for javaClass() +Compile bytecode for 100.toInt() +Compile bytecode for 100.toLong() Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/vars.out b/idea/testData/debugger/tinyApp/outs/vars.out index 764afeee9d0..0a19db7c231 100644 --- a/idea/testData/debugger/tinyApp/outs/vars.out +++ b/idea/testData/debugger/tinyApp/outs/vars.out @@ -2,6 +2,8 @@ LineBreakpoint created at vars.kt:7 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! vars.VarsPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' vars.kt:6 +Compile bytecode for a +Compile bytecode for a += 1 Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/clearCache.kt b/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/clearCache.kt new file mode 100644 index 00000000000..99f8c6c8f46 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/clearCache.kt @@ -0,0 +1,185 @@ +package clearCache + +import java.util.ArrayList +import java.util.HashSet + +fun primitiveTypes() { + if (true) { + val a: Any = 0 + // EXPRESSION: a + // RESULT: instance of java.lang.Integer(id=ID): Ljava/lang/Integer; + //Breakpoint! + val b = 1 + } + + if (true) { + val a = 1 + // EXPRESSION: a + // RESULT: 1: I + //Breakpoint! + val b = 1 + } + + for (i in 1..2) { + // EXPRESSION: i + // RESULT: 1: I + + // EXPRESSION: i + // RESULT: 2: I + + //Breakpoint! + val b = 1 + } + + for (i in 5.0..6.0) { + // EXPRESSION: i + // RESULT: 5.0: D + + // EXPRESSION: i + // RESULT: 6.0: D + + //Breakpoint! + val b = 1 + } +} + +fun subType() { + if (true) { + val o = Base() + // EXPRESSION: o.test() + // RESULT: 100: I + //Breakpoint! + val b = 1 + } + + if (true) { + val o = Derived() + // EXPRESSION: o.test() + // RESULT: 200: I + //Breakpoint! + val b = 1 + } +} + +open class Base { + open fun test() = 100 +} + +class Derived: Base() { + override fun test() = 200 +} + +fun subTypePlatform() { + if (true) { + val c: MutableList = ArrayList() + // EXPRESSION: c.size() + // RESULT: 0: I + //Breakpoint! + val b = 1 + } + + if (true) { + val c: List = ArrayList() + // EXPRESSION: c.size() + // RESULT: 0: I + //Breakpoint! + val b = 1 + } + + if (true) { + val c = ArrayList() + c.add("a") + // EXPRESSION: c.size() + // RESULT: 1: I + //Breakpoint! + val b = 1 + } + + if (true) { + val c = ArrayList() + c.add(1) + c.add(2) + // EXPRESSION: c.size() + // RESULT: 2: I + //Breakpoint! + val b = 1 + } + + if (true) { + val c = HashSet() + // EXPRESSION: c.size() + // RESULT: 0: I + //Breakpoint! + val b = 1 + } +} + +fun innerClass() { + if (true) { + val o = TestInnerClasses.Base() + // EXPRESSION: o.test() + // RESULT: 100: I + //Breakpoint! + val b = 1 + } + + if (true) { + val o = TestInnerClasses.Derived() + // EXPRESSION: o.test() + // RESULT: 200: I + //Breakpoint! + val b = 1 + } +} + +class TestInnerClasses { + open class Base { + open fun test() = 100 + } + + class Derived: Base() { + override fun test() = 200 + } +} + +fun objects() { + // EXPRESSION: obj.test() + // RESULT: 1: I + //Breakpoint! + val a1 = 1 + + // EXPRESSION: obj.test() + // RESULT: 1: I + //Breakpoint! + val a2 = 1 + + if (true) { + val o: BaseObject = obj + // EXPRESSION: o.test() + // RESULT: 1: I + //Breakpoint! + val b = 1 + } + + if (true) { + val o = obj + // EXPRESSION: o.test() + // RESULT: 1: I + //Breakpoint! + val b = 1 + } +} + +val obj = object: BaseObject() { } + +open class BaseObject { + fun test() = 1 +} + +fun main(args: Array) { + primitiveTypes() + subType() + subTypePlatform() + innerClass() + objects() +} diff --git a/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/exceptions.kt b/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/exceptions.kt new file mode 100644 index 00000000000..deb56b87e41 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/exceptions.kt @@ -0,0 +1,65 @@ +package exceptions + +import java.util.ArrayList + +fun throwException() { + // EXPRESSION: fail() + // RESULT: instance of java.lang.UnsupportedOperationException(id=ID): Ljava/lang/UnsupportedOperationException; + //Breakpoint! + val a = 1 + + // EXPRESSION: fail() + // RESULT: instance of java.lang.UnsupportedOperationException(id=ID): Ljava/lang/UnsupportedOperationException; + //Breakpoint! + val b = 1 +} + +fun fail() { + throw UnsupportedOperationException() +} + +fun classCast() { + val o = Base() + // EXPRESSION: o as Derived + // RESULT: java.lang.ClassCastException: exceptions.Base cannot be cast to exceptions.Derived: Ljava/lang/ClassCastException; + //Breakpoint! + val a = 1 + + // EXPRESSION: o as Derived + // RESULT: java.lang.ClassCastException: exceptions.Base cannot be cast to exceptions.Derived: Ljava/lang/ClassCastException; + //Breakpoint! + val b = 1 +} + + +fun genericClassCast() { + if (true) { + val c = ArrayList() + c.add(1) + // EXPRESSION: c.get(0) + // RESULT: 1: I + //Breakpoint! + val b = 1 + } + + if (true) { + val c = ArrayList() + c.add("a") + // EXPRESSION: c.get(0) + // RESULT: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number: Ljava/lang/ClassCastException; + //Breakpoint! + val b = 1 + } +} + +open class Base { + private fun test(): Int = 1 +} + +class Derived: Base() + +fun main(args: Array) { + throwException() + classCast() + genericClassCast() +} \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/privateMember.kt b/idea/testData/debugger/tinyApp/src/evaluate/privateMember.kt deleted file mode 100644 index 8559185ed2c..00000000000 --- a/idea/testData/debugger/tinyApp/src/evaluate/privateMember.kt +++ /dev/null @@ -1,24 +0,0 @@ -package privateMember - -fun main(args: Array) { - //Breakpoint! - args.size -} - -class MyClass { - private fun privateFun() = 1 - private val privateVal = 1 - - private class PrivateClass { - val a = 1 - } -} - -// EXPRESSION: MyClass().privateFun() -// RESULT: 1: I - -// EXPRESSION: MyClass().privateVal -// RESULT: 1: I - -// EXPRESSION: MyClass.PrivateClass().a -// RESULT: 1: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/abstractFunCall.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/abstractFunCall.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/abstractFunCall.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/abstractFunCall.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/arrays.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/arrays.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/arrays.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/arrays.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/classFromAnotherPackage.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/classFromAnotherPackage.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/classFromAnotherPackage.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/classFromAnotherPackage.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/classObjectVal.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/classObjectVal.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/classObjectVal.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/classObjectVal.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/collections.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/collections.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/collections.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/collections.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/collections.kt.fragment b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/collections.kt.fragment similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/collections.kt.fragment rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/collections.kt.fragment diff --git a/idea/testData/debugger/tinyApp/src/evaluate/dependentOnFile.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/dependentOnFile.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/dependentOnFile.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/dependentOnFile.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/doubles.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/doubles.kt new file mode 100644 index 00000000000..1ba2c60ef79 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/doubles.kt @@ -0,0 +1,11 @@ +package doubles + +fun main(args: Array) { + val d1 = 1.0 + val d2 = 3.0 + //Breakpoint! + args.size +} + +// EXPRESSION: d1 + d2 +// RESULT: 4.0: D \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/enums.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/enums.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/enums.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/enums.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/errors.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/errors.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/errors.kt.fragment b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt.fragment similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/errors.kt.fragment rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt.fragment diff --git a/idea/testData/debugger/tinyApp/src/evaluate/errors.kt.fragment2 b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt.fragment2 similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/errors.kt.fragment2 rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt.fragment2 diff --git a/idea/testData/debugger/tinyApp/src/evaluate/extractLocalVariables.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractLocalVariables.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/extractLocalVariables.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractLocalVariables.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/extractThis.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractThis.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/extractThis.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractThis.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/extractVariablesFromCall.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractVariablesFromCall.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/extractVariablesFromCall.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractVariablesFromCall.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/imports.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/imports.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/imports.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/imports.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/insertInBlock.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/insertInBlock.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/insertInBlock.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/insertInBlock.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/multilineExpressionAtBreakpoint.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/multilineExpressionAtBreakpoint.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/multilineExpressionAtBreakpoint.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/multilineExpressionAtBreakpoint.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/privateMember.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/privateMember.kt new file mode 100644 index 00000000000..1ced9ae98d6 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/privateMember.kt @@ -0,0 +1,45 @@ +package privateMember + +fun main(args: Array) { + val base = Base() + val derived = Derived() + val derivedAsBase: Base = Derived() + + //Breakpoint! + args.size +} + +class MyClass { + private fun privateFun() = 1 + private val privateVal = 1 + + private class PrivateClass { + val a = 1 + } +} + +open class Base { + private fun privateFun() = 2 +} + +class Derived: Base() { + private fun privateFun() = 3 +} + +// EXPRESSION: MyClass().privateFun() +// RESULT: 1: I + +// EXPRESSION: MyClass().privateVal +// RESULT: 1: I + +// EXPRESSION: MyClass.PrivateClass().a +// RESULT: 1: I + +// EXPRESSION: base.privateFun() +// RESULT: 2: I + +// EXPRESSION: derived.privateFun() +// RESULT: 3: I + +// EXPRESSION: derivedAsBase.privateFun() +// RESULT: 2: I diff --git a/idea/testData/debugger/tinyApp/src/evaluate/protectedMember.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/protectedMember.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/protectedMember.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/protectedMember.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/simple.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/simple.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/simple.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/simple.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/simple.kt.fragment b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/simple.kt.fragment similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/simple.kt.fragment rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/simple.kt.fragment diff --git a/idea/testData/debugger/tinyApp/src/evaluate/stdlib.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/stdlib.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/stdlib.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/stdlib.kt diff --git a/idea/testData/debugger/tinyApp/src/evaluate/vars.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/vars.kt similarity index 100% rename from idea/testData/debugger/tinyApp/src/evaluate/vars.kt rename to idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/vars.kt diff --git a/idea/testData/formatter/When.after.inv.kt b/idea/testData/formatter/When.after.inv.kt index 0a105c79269..d438d0d6c24 100644 --- a/idea/testData/formatter/When.after.inv.kt +++ b/idea/testData/formatter/When.after.inv.kt @@ -28,6 +28,9 @@ fun some(x: Any) { when (true) { } + + when { + } } // SET_FALSE: ALIGN_IN_COLUMNS_CASE_BRANCH \ No newline at end of file diff --git a/idea/testData/formatter/When.after.kt b/idea/testData/formatter/When.after.kt index a2237d8f753..7e4f33040b9 100644 --- a/idea/testData/formatter/When.after.kt +++ b/idea/testData/formatter/When.after.kt @@ -28,6 +28,9 @@ fun some(x: Any) { when (true) { } + + when { + } } // SET_FALSE: ALIGN_IN_COLUMNS_CASE_BRANCH \ No newline at end of file diff --git a/idea/testData/formatter/When.kt b/idea/testData/formatter/When.kt index 616c0f13a06..b48ddce8f80 100644 --- a/idea/testData/formatter/When.kt +++ b/idea/testData/formatter/When.kt @@ -39,6 +39,8 @@ else->1 { } + + when {} } // SET_FALSE: ALIGN_IN_COLUMNS_CASE_BRANCH \ No newline at end of file diff --git a/idea/testData/intentions/branched/ifThenToDoubleBang/noCondition.kt b/idea/testData/intentions/branched/ifThenToDoubleBang/noCondition.kt index 92aa62d49d0..38fa33c3b29 100644 --- a/idea/testData/intentions/branched/ifThenToDoubleBang/noCondition.kt +++ b/idea/testData/intentions/branched/ifThenToDoubleBang/noCondition.kt @@ -1,7 +1,5 @@ // WITH_RUNTIME // IS_APPLICABLE: false -// ERROR: Type mismatch.
Required:kotlin.Boolean
Found:() → kotlin.String?
-// ERROR: Condition must be of type kotlin.Boolean, but is of type () -> kotlin.String? fun main(args: Array) { val foo: String? = "foo" if { diff --git a/idea/testData/intentions/branched/ifThenToElvis/noCondition.kt b/idea/testData/intentions/branched/ifThenToElvis/noCondition.kt index 4a70d1eb0bc..4328f8a0770 100644 --- a/idea/testData/intentions/branched/ifThenToElvis/noCondition.kt +++ b/idea/testData/intentions/branched/ifThenToElvis/noCondition.kt @@ -1,6 +1,4 @@ // IS_APPLICABLE: false -// ERROR: Type mismatch.
Required:kotlin.Boolean
Found:() → kotlin.String?
-// ERROR: Condition must be of type kotlin.Boolean, but is of type () -> kotlin.String? fun main(args: Array) { val foo: String? = "foo" val bar = "bar" diff --git a/idea/testData/intentions/branched/ifThenToSafeAccess/noCondition.kt b/idea/testData/intentions/branched/ifThenToSafeAccess/noCondition.kt index 6b0aff7dff3..4a4e380e71e 100644 --- a/idea/testData/intentions/branched/ifThenToSafeAccess/noCondition.kt +++ b/idea/testData/intentions/branched/ifThenToSafeAccess/noCondition.kt @@ -1,6 +1,4 @@ // IS_APPLICABLE: false -// ERROR: Type mismatch.
Required:kotlin.Boolean
Found:() → kotlin.Int
-// ERROR: Condition must be of type kotlin.Boolean, but is of type () -> kotlin.Int // ERROR: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type kotlin.String? fun main(args: Array) { val foo: String? = "foo" diff --git a/idea/testData/intentions/swapBinaryExpression/is.kt b/idea/testData/intentions/swapBinaryExpression/is.kt index 40ffa670a91..b94334880a8 100644 --- a/idea/testData/intentions/swapBinaryExpression/is.kt +++ b/idea/testData/intentions/swapBinaryExpression/is.kt @@ -1,4 +1,5 @@ // IS_APPLICABLE: false +// ERROR: Expression 'if "test" is String' of type 'kotlin.Unit' cannot be invoked as a function. The function invoke() is not found fun doSomething(a: T) {} diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeMultiFakeOverride.kt b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeMultiFakeOverride.kt new file mode 100644 index 00000000000..9d033b6e447 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeMultiFakeOverride.kt @@ -0,0 +1,13 @@ +// "class org.jetbrains.jet.plugin.quickfix.ChangeParameterTypeFix" "false" +// ERROR: Type mismatch.
Required:kotlin.Int
Found:kotlin.String
+trait A { + fun f(i: Int): Boolean +} + +open class AA { + fun f(i: Int) = true +} + +class AAA: AA(), A + +val c = AAA().f("") \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverride.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverride.kt new file mode 100644 index 00000000000..dbcb8365484 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverride.kt @@ -0,0 +1,19 @@ +// "Change 'AA.f' function return type to 'Boolean'" "false" +// ACTION: Change 'AAA.g' function return type to 'Int' +// ACTION: Convert to expression body +// ACTION: Disable 'Convert to Expression Body' +// ACTION: Edit intention settings +// ERROR: Type mismatch.
Required:kotlin.Boolean
Found:kotlin.Int
+trait A { + fun f(): Int +} + +open class AA { + fun f() = 3 +} + +class AAA: AA(), A { + fun g(): Boolean { + return f() + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverrideForOperatorConvention.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverrideForOperatorConvention.kt new file mode 100644 index 00000000000..ae55376a13e --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverrideForOperatorConvention.kt @@ -0,0 +1,22 @@ +// "Change 'AA.contains' function return type to 'Int'" "false" +// ACTION: Change 'AAA.g' function return type to 'Boolean' +// ACTION: Convert to expression body +// ACTION: Disable 'Convert to Expression Body' +// ACTION: Disable 'Replace Overloaded Operator With Function Call' +// ACTION: Edit intention settings +// ACTION: Edit intention settings +// ACTION: Replace overloaded operator with function call +// ERROR: Type mismatch.
Required:kotlin.Int
Found:kotlin.Boolean
+trait A { + fun contains(i: Int): Boolean +} + +open class AA { + fun contains(i: Int) = true +} + +class AAA: AA(), A { + fun g(): Int { + return 3 in this + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/basic/fragmentWithComment.kt b/idea/testData/refactoring/extractFunction/basic/fragmentWithComment.kt index 18c78fd61bb..3372cfd9265 100644 --- a/idea/testData/refactoring/extractFunction/basic/fragmentWithComment.kt +++ b/idea/testData/refactoring/extractFunction/basic/fragmentWithComment.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { // test diff --git a/idea/testData/refactoring/extractFunction/basic/fragmentWithComment.kt.after b/idea/testData/refactoring/extractFunction/basic/fragmentWithComment.kt.after index 608dabf999a..b8aaaec2df4 100644 --- a/idea/testData/refactoring/extractFunction/basic/fragmentWithComment.kt.after +++ b/idea/testData/refactoring/extractFunction/basic/fragmentWithComment.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { if (b(a)) return a diff --git a/idea/testData/refactoring/extractFunction/basic/fragmentWithMultilineComment.kt b/idea/testData/refactoring/extractFunction/basic/fragmentWithMultilineComment.kt index 7a6adf3d142..1a112d5181b 100644 --- a/idea/testData/refactoring/extractFunction/basic/fragmentWithMultilineComment.kt +++ b/idea/testData/refactoring/extractFunction/basic/fragmentWithMultilineComment.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { /* diff --git a/idea/testData/refactoring/extractFunction/basic/fragmentWithMultilineComment.kt.after b/idea/testData/refactoring/extractFunction/basic/fragmentWithMultilineComment.kt.after index 442909f5953..1879862bb0a 100644 --- a/idea/testData/refactoring/extractFunction/basic/fragmentWithMultilineComment.kt.after +++ b/idea/testData/refactoring/extractFunction/basic/fragmentWithMultilineComment.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { if (b(a)) return a diff --git a/idea/testData/refactoring/extractFunction/basic/refInReturn.kt b/idea/testData/refactoring/extractFunction/basic/refInReturn.kt index 0fd72488273..029b2dca931 100644 --- a/idea/testData/refactoring/extractFunction/basic/refInReturn.kt +++ b/idea/testData/refactoring/extractFunction/basic/refInReturn.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { println(a) diff --git a/idea/testData/refactoring/extractFunction/basic/refInReturn.kt.after b/idea/testData/refactoring/extractFunction/basic/refInReturn.kt.after index ffe390de69e..e9052bbf124 100644 --- a/idea/testData/refactoring/extractFunction/basic/refInReturn.kt.after +++ b/idea/testData/refactoring/extractFunction/basic/refInReturn.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { if (b(a)) return a diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIf.kt b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIf.kt index f836b2a6581..0963d801a51 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIf.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIf.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIf.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIf.kt.after index e10096f1f3d..3efbe1b4c57 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIf.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIf.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfElse.kt b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfElse.kt index 03e115b80d6..92d438a0062 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfElse.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfElse.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfElse.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfElse.kt.after index ac6cf45ac2c..867bfdceda6 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfElse.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithIfElse.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithWhen.kt b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithWhen.kt index 4286e85cc20..f564b6bf2df 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithWhen.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithWhen.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithWhen.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithWhen.kt.after index 4c18664b220..239d825363d 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithWhen.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalBreakWithWhen.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIf.kt b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIf.kt index ecd386b198d..3158bd16036 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIf.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIf.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIf.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIf.kt.after index 4fc2c0ba18c..154bd1413a6 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIf.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIf.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIfElse.kt b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIfElse.kt index 199f2ba5304..819f00074b8 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIfElse.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIfElse.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIfElse.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIfElse.kt.after index a1c786aa896..0ef66d95783 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIfElse.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithIfElse.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithWhen.kt b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithWhen.kt index ffa88f296c7..741510eda5a 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithWhen.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithWhen.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithWhen.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithWhen.kt.after index 81e18d6d4a9..7e4c43b906e 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithWhen.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/conditionalReturnWithWhen.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIf.kt b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIf.kt index 0e4a5dcd7d7..1af325848c9 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIf.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIf.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIf.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIf.kt.after index e0378144224..580507294f3 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIf.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIf.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIfElse.kt b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIfElse.kt index 7bb6f8d2bde..ceddd650382 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIfElse.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIfElse.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIfElse.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIfElse.kt.after index 2c2cb51f5d2..fb152f9057a 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIfElse.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithIfElse.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithWhen.kt b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithWhen.kt index f25eda5649f..a5ff642baa0 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithWhen.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithWhen.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithWhen.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithWhen.kt.after index f40ffbefe6d..1d272a7ca5d 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithWhen.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/conditionalJumps/unconditionalBreakWithWhen.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCF.kt b/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCF.kt index 9e380c0605e..626f08973f4 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCF.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCF.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int, Comparable +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any // SIBLING: fun foo(a: Int) { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCF.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCF.kt.after index 70a1a7925d7..4ccdf286943 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCF.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCF.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int, Comparable +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any // SIBLING: fun foo(a: Int) { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithJumps.kt b/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithJumps.kt index e2399edb49f..7dcfff262f3 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithJumps.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithJumps.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int) { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithJumps.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithJumps.kt.after index 0a6786457c3..f032a9a01d5 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithJumps.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/defaultCFWithJumps.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int) { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIf.kt b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIf.kt index c9d2cd5315d..7b4ae2ec974 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIf.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIf.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any fun bar(a: Int): Int { println(a) return a + 10 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIf.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIf.kt.after index b2f3082b36f..b7eca1131bd 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIf.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIf.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any fun bar(a: Int): Int { println(a) return a + 10 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIfNoBlocks.kt b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIfNoBlocks.kt index 776c48ce0a4..7ee6d3ef64d 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIfNoBlocks.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIfNoBlocks.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any fun bar(a: Int): Int { println(a) return a + 10 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIfNoBlocks.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIfNoBlocks.kt.after index 8dbbebfbb6e..2c123ba930f 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIfNoBlocks.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithIfNoBlocks.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any fun bar(a: Int): Int { println(a) return a + 10 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhen.kt b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhen.kt index 7d8e025b621..e4e643561b5 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhen.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhen.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any fun bar(a: Int): Int { println(a) return a + 10 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhen.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhen.kt.after index 82c1f66c80e..e6422989354 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhen.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhen.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any fun bar(a: Int): Int { println(a) return a + 10 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhenNoBlocks.kt b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhenNoBlocks.kt index 88a828799ed..3b98c0fc77c 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhenNoBlocks.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhenNoBlocks.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any fun bar(a: Int): Int { println(a) return a + 10 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhenNoBlocks.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhenNoBlocks.kt.after index b8aa0d9e44d..bf7a312045e 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhenNoBlocks.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/default/ignoredReturnValueWithWhenNoBlocks.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any fun bar(a: Int): Int { println(a) return a + 10 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithIf.kt b/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithIf.kt index 1d23aa7b381..3984a3238a6 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithIf.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithIf.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithIf.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithIf.kt.after index 96feeacb740..fce0d54ffba 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithIf.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithIf.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithWhen.kt b/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithWhen.kt index 117adfe3791..8b3ddc1ca47 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithWhen.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithWhen.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithWhen.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithWhen.kt.after index f8fceed3237..cf488a71e8f 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithWhen.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/definiteReturnWithWhen.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/singleDefiniteReturn.kt b/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/singleDefiniteReturn.kt index fa31f31fdda..43084f4ef5e 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/singleDefiniteReturn.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/singleDefiniteReturn.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/singleDefiniteReturn.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/singleDefiniteReturn.kt.after index 2ac53541783..3b3bc9b1e0c 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/singleDefiniteReturn.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/definiteReturns/singleDefiniteReturn.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfCondition.kt b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfCondition.kt index c5e075ff91c..a84a001f9d2 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfCondition.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfCondition.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfCondition.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfCondition.kt.after index 1085b675856..594bee9b23e 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfCondition.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfCondition.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfElse.kt b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfElse.kt index 39ac60a8466..d5df8a1f9af 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfElse.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfElse.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfElse.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfElse.kt.after index 957aa383f92..ec9b09d88a7 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfElse.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInIfElse.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenBranch.kt b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenBranch.kt index afee5edb18f..6bd445a3073 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenBranch.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenBranch.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenBranch.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenBranch.kt.after index e916a7f5b11..ae9d877f7ce 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenBranch.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenBranch.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenSubject.kt b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenSubject.kt index 5e4cca26943..c6a90882e00 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenSubject.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenSubject.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenSubject.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenSubject.kt.after index 28242ea436c..3a3bd47e9d4 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenSubject.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExprInWhenSubject.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExpressionBodyFunction.kt b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExpressionBodyFunction.kt index d2cfaeddfe5..b3b22875daf 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExpressionBodyFunction.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExpressionBodyFunction.kt @@ -1,2 +1,4 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int, b: Int): Int = a + b diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExpressionBodyFunction.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExpressionBodyFunction.kt.after index c5ef5bfc557..3a7fc579e04 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExpressionBodyFunction.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalExpressionBodyFunction.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int, b: Int): Int = i(a, b) diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalIfExpr.kt b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalIfExpr.kt index 3222a55b7d7..66668cd0b4b 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalIfExpr.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalIfExpr.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalIfExpr.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalIfExpr.kt.after index effcbf7e4cc..61c2300399c 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalIfExpr.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalIfExpr.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalWhenExpr.kt b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalWhenExpr.kt index 3b198ecc4be..b3e1079cea2 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalWhenExpr.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalWhenExpr.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalWhenExpr.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalWhenExpr.kt.after index 3c7904f49d0..42d92c15c5c 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalWhenExpr.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalWhenExpr.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/simpleEvalExpr.kt b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/simpleEvalExpr.kt index 77991cf0170..d42e002c5c0 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/simpleEvalExpr.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/simpleEvalExpr.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/simpleEvalExpr.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/simpleEvalExpr.kt.after index 2ac53541783..3b3bc9b1e0c 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/simpleEvalExpr.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/simpleEvalExpr.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaEmptyArgList.kt b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaEmptyArgList.kt new file mode 100644 index 00000000000..12fb1251f33 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaEmptyArgList.kt @@ -0,0 +1,6 @@ +fun Array.check(f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array) { + t.check() { it + 1 > 1 } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaEmptyArgList.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaEmptyArgList.kt.after new file mode 100644 index 00000000000..c21ead68b75 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaEmptyArgList.kt.after @@ -0,0 +1,10 @@ +fun Array.check(f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array) { + t.check(function()) +} + +fun function(): (Int) -> Boolean { + return { it + 1 > 1 } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNoArgList.kt b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNoArgList.kt new file mode 100644 index 00000000000..8abdecfdd41 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNoArgList.kt @@ -0,0 +1,6 @@ +fun Array.check(f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array) { + t.check { it + 1 > 1 } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNoArgList.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNoArgList.kt.after new file mode 100644 index 00000000000..c21ead68b75 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNoArgList.kt.after @@ -0,0 +1,10 @@ +fun Array.check(f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array) { + t.check(function()) +} + +fun function(): (Int) -> Boolean { + return { it + 1 > 1 } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNonEmptyArgList.kt b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNonEmptyArgList.kt new file mode 100644 index 00000000000..be50018ca90 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNonEmptyArgList.kt @@ -0,0 +1,6 @@ +fun Array.check(a: Int, b: Int f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array) { + t.check(1, 2) { it + 1 > 1 } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNonEmptyArgList.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNonEmptyArgList.kt.after new file mode 100644 index 00000000000..567ab21da22 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNonEmptyArgList.kt.after @@ -0,0 +1,10 @@ +fun Array.check(a: Int, b: Int f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array) { + t.check(1, 2, function()) +} + +fun function(): (Int) -> Boolean { + return { it + 1 > 1 } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValue.kt b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValue.kt index 4fa1218b258..50f8e17ccfa 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValue.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValue.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { var b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValue.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValue.kt.after index d02accf3487..f125443db71 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValue.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValue.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { var b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIf.kt b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIf.kt index 02665c4eb3e..2d7a4b3b1c6 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIf.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIf.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int, Comparable +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { var b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIf.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIf.kt.after index 211b37c956d..34458f1ff65 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIf.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIf.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int, Comparable +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { var b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIfElse.kt b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIfElse.kt index cd0880bf48c..c42c15350e1 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIfElse.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIfElse.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { var b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIfElse.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIfElse.kt.after index f85082d6c38..c4af982ba6b 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIfElse.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithIfElse.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { var b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhen.kt b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhen.kt index 710aebe5ff3..c804d9d1eb2 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhen.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhen.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int, Comparable +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { var b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhen.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhen.kt.after index d51486fd376..a2ce6551c1c 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhen.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhen.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int, Comparable +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { var b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhenElse.kt b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhenElse.kt index 62cb4836a34..e49a2b0e424 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhenElse.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhenElse.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { var b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhenElse.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhenElse.kt.after index b7dfbc2c107..70755a7e64d 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhenElse.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/outputValues/singleOutputValueWithWhenElse.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { var b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/throws/breakWithThrow.kt b/idea/testData/refactoring/extractFunction/controlFlow/throws/breakWithThrow.kt index 60e5b4f04e6..4d97b3dae34 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/throws/breakWithThrow.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/throws/breakWithThrow.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/throws/breakWithThrow.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/throws/breakWithThrow.kt.after index b8eb407c5da..1849ddf19f7 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/throws/breakWithThrow.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/throws/breakWithThrow.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/throws/continueWithThrow.kt b/idea/testData/refactoring/extractFunction/controlFlow/throws/continueWithThrow.kt index 919ffd16e73..8b775628609 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/throws/continueWithThrow.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/throws/continueWithThrow.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/throws/continueWithThrow.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/throws/continueWithThrow.kt.after index 3241bcc9ddd..35e7cbd7555 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/throws/continueWithThrow.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/throws/continueWithThrow.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/throws/evalExpressionWithThrow.kt b/idea/testData/refactoring/extractFunction/controlFlow/throws/evalExpressionWithThrow.kt index 3710051cd59..e3ac46dc63a 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/throws/evalExpressionWithThrow.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/throws/evalExpressionWithThrow.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/throws/evalExpressionWithThrow.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/throws/evalExpressionWithThrow.kt.after index bda988ff2f0..a31337f0084 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/throws/evalExpressionWithThrow.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/throws/evalExpressionWithThrow.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/throws/nonValuedReturnWithThrow.kt b/idea/testData/refactoring/extractFunction/controlFlow/throws/nonValuedReturnWithThrow.kt index 7c1c6f1a4cf..5e830e28a1d 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/throws/nonValuedReturnWithThrow.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/throws/nonValuedReturnWithThrow.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int) { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/throws/nonValuedReturnWithThrow.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/throws/nonValuedReturnWithThrow.kt.after index e2c66d8ce95..c11246bb9dc 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/throws/nonValuedReturnWithThrow.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/throws/nonValuedReturnWithThrow.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int) { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/throws/outputValueWithThrow.kt b/idea/testData/refactoring/extractFunction/controlFlow/throws/outputValueWithThrow.kt index 514aa2941ff..06211d31505 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/throws/outputValueWithThrow.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/throws/outputValueWithThrow.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { var b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/throws/outputValueWithThrow.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/throws/outputValueWithThrow.kt.after index 430e72c1b3a..466c582391d 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/throws/outputValueWithThrow.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/throws/outputValueWithThrow.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { var b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/throws/returnWithThrow.kt b/idea/testData/refactoring/extractFunction/controlFlow/throws/returnWithThrow.kt index fcff707f1d0..d0c974d147a 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/throws/returnWithThrow.kt +++ b/idea/testData/refactoring/extractFunction/controlFlow/throws/returnWithThrow.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/throws/returnWithThrow.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/throws/returnWithThrow.kt.after index 819b4b274e0..9fed3c2fe1b 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/throws/returnWithThrow.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/throws/returnWithThrow.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int): Int { val b: Int = 1 diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt new file mode 100644 index 00000000000..b061ff68f50 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt @@ -0,0 +1,11 @@ +// SIBLING: +fun main(args: Array) { + val a = 1 + val t = object: T { + override fun foo(n: Int) = n + a + } +} + +trait T { + fun foo(n: Int): Int +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt.conflicts b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt.conflicts new file mode 100644 index 00000000000..87517ea9e65 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt.conflicts @@ -0,0 +1 @@ +Following variables are used outside of selected code fragment: a \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt new file mode 100644 index 00000000000..f0f0342ec3a --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt @@ -0,0 +1,9 @@ +// SIBLING: +fun main(args: Array) { + val a = 1 + lambda { + a + } +} + +fun lambda(f: () -> Unit) {} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt.conflicts b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt.conflicts new file mode 100644 index 00000000000..87517ea9e65 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt.conflicts @@ -0,0 +1 @@ +Following variables are used outside of selected code fragment: a \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt new file mode 100644 index 00000000000..c0461c825ad --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt @@ -0,0 +1,5 @@ +// SIBLING: +fun main(args: Array) { + val a = 1 + fun foo() = a +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt.conflicts b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt.conflicts new file mode 100644 index 00000000000..87517ea9e65 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt.conflicts @@ -0,0 +1 @@ +Following variables are used outside of selected code fragment: a \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/defaultContainer/classFunction.kt b/idea/testData/refactoring/extractFunction/defaultContainer/classFunction.kt index 5b2f79699e1..6cf938ac03d 100644 --- a/idea/testData/refactoring/extractFunction/defaultContainer/classFunction.kt +++ b/idea/testData/refactoring/extractFunction/defaultContainer/classFunction.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int class A { class B { fun foo(a: Int, b: Int): Int { diff --git a/idea/testData/refactoring/extractFunction/defaultContainer/classFunction.kt.after b/idea/testData/refactoring/extractFunction/defaultContainer/classFunction.kt.after index 41d443a15c6..efd25e31a75 100644 --- a/idea/testData/refactoring/extractFunction/defaultContainer/classFunction.kt.after +++ b/idea/testData/refactoring/extractFunction/defaultContainer/classFunction.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int class A { class B { fun foo(a: Int, b: Int): Int { diff --git a/idea/testData/refactoring/extractFunction/defaultContainer/topLevelFunction.kt b/idea/testData/refactoring/extractFunction/defaultContainer/topLevelFunction.kt index 3d8111d8964..943cd2cb1de 100644 --- a/idea/testData/refactoring/extractFunction/defaultContainer/topLevelFunction.kt +++ b/idea/testData/refactoring/extractFunction/defaultContainer/topLevelFunction.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int fun foo(a: Int, b: Int): Int { return a + b - 1 } \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/defaultContainer/topLevelFunction.kt.after b/idea/testData/refactoring/extractFunction/defaultContainer/topLevelFunction.kt.after index 7d4acfb97ea..ae7efed9cba 100644 --- a/idea/testData/refactoring/extractFunction/defaultContainer/topLevelFunction.kt.after +++ b/idea/testData/refactoring/extractFunction/defaultContainer/topLevelFunction.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int fun foo(a: Int, b: Int): Int { return i(a, b) } diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt new file mode 100644 index 00000000000..4dafde070ed --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt @@ -0,0 +1,14 @@ +// PARAM_TYPES: kotlin.String, Comparable, CharSequence, kotlin.Any +// PARAM_TYPES: X +class X { + fun add(t: T) { + + } +} + +// SIBLING: +fun foo(s: String?, x: X) { + when { + s != null -> x.add(s) + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt.after b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt.after new file mode 100644 index 00000000000..e16d1ea3903 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt.after @@ -0,0 +1,18 @@ +// PARAM_TYPES: kotlin.String, Comparable, CharSequence, kotlin.Any +// PARAM_TYPES: X +class X { + fun add(t: T) { + + } +} + +// SIBLING: +fun foo(s: String?, x: X) { + when { + s != null -> unit(s, x) + } +} + +fun unit(s: String, x: X) { + x.add(s) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nullableTypes.kt b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nullableTypes.kt new file mode 100644 index 00000000000..ce80d833f72 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nullableTypes.kt @@ -0,0 +1,14 @@ +// PARAM_TYPES: kotlin.String?, kotlin.Comparable?, kotlin.CharSequence?, kotlin.Any? +// PARAM_TYPES: X +class X { + fun add(t: T) { + + } +} + +// SIBLING: +fun foo(s: String?, x: X) { + when { + s != null -> x.add(s) + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nullableTypes.kt.after b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nullableTypes.kt.after new file mode 100644 index 00000000000..b3b116f5ad4 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nullableTypes.kt.after @@ -0,0 +1,18 @@ +// PARAM_TYPES: kotlin.String?, kotlin.Comparable?, kotlin.CharSequence?, kotlin.Any? +// PARAM_TYPES: X +class X { + fun add(t: T) { + + } +} + +// SIBLING: +fun foo(s: String?, x: X) { + when { + s != null -> unit(s, x) + } +} + +fun unit(s: String?, x: X) { + x.add(s) +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy1.kt b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy1.kt new file mode 100644 index 00000000000..0110855a2cf --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy1.kt @@ -0,0 +1,35 @@ +//PARAM_TYPES: C, AImpl, A +trait A { + fun doA() +} + +open class AImpl: A { + override fun doA() { + throw UnsupportedOperationException() + } +} + +trait B { + fun doB() +} + +class C: AImpl(), B { + override fun doA() { + throw UnsupportedOperationException() + } + + override fun doB() { + throw UnsupportedOperationException() + } + + fun doC() { + throw UnsupportedOperationException() + } +} + +// SIBLING: +fun foo(c: C) { + c.doA() + c.doB() + c.doC() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy1.kt.after b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy1.kt.after new file mode 100644 index 00000000000..c0aa5718d2d --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy1.kt.after @@ -0,0 +1,39 @@ +//PARAM_TYPES: C, AImpl, A +trait A { + fun doA() +} + +open class AImpl: A { + override fun doA() { + throw UnsupportedOperationException() + } +} + +trait B { + fun doB() +} + +class C: AImpl(), B { + override fun doA() { + throw UnsupportedOperationException() + } + + override fun doB() { + throw UnsupportedOperationException() + } + + fun doC() { + throw UnsupportedOperationException() + } +} + +// SIBLING: +fun foo(c: C) { + unit(c) + c.doB() + c.doC() +} + +fun unit(c: C) { + c.doA() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy2.kt b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy2.kt new file mode 100644 index 00000000000..c5d4010f69d --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy2.kt @@ -0,0 +1,35 @@ +//PARAM_TYPES: C, B +trait A { + fun doA() +} + +open class AImpl: A { + override fun doA() { + throw UnsupportedOperationException() + } +} + +trait B { + fun doB() +} + +class C: AImpl(), B { + override fun doA() { + throw UnsupportedOperationException() + } + + override fun doB() { + throw UnsupportedOperationException() + } + + fun doC() { + throw UnsupportedOperationException() + } +} + +// SIBLING: +fun foo(c: C) { + c.doA() + c.doB() + c.doC() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy2.kt.after b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy2.kt.after new file mode 100644 index 00000000000..96645ea7142 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy2.kt.after @@ -0,0 +1,39 @@ +//PARAM_TYPES: C, B +trait A { + fun doA() +} + +open class AImpl: A { + override fun doA() { + throw UnsupportedOperationException() + } +} + +trait B { + fun doB() +} + +class C: AImpl(), B { + override fun doA() { + throw UnsupportedOperationException() + } + + override fun doB() { + throw UnsupportedOperationException() + } + + fun doC() { + throw UnsupportedOperationException() + } +} + +// SIBLING: +fun foo(c: C) { + c.doA() + unit(c) + c.doC() +} + +fun unit(c: C) { + c.doB() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy3.kt b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy3.kt new file mode 100644 index 00000000000..578290918ab --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy3.kt @@ -0,0 +1,35 @@ +//PARAM_TYPES: C +trait A { + fun doA() +} + +open class AImpl: A { + override fun doA() { + throw UnsupportedOperationException() + } +} + +trait B { + fun doB() +} + +class C: AImpl(), B { + override fun doA() { + throw UnsupportedOperationException() + } + + override fun doB() { + throw UnsupportedOperationException() + } + + fun doC() { + throw UnsupportedOperationException() + } +} + +// SIBLING: +fun foo(c: C) { + c.doA() + c.doB() + c.doC() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy3.kt.after b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy3.kt.after new file mode 100644 index 00000000000..05d6290919b --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy3.kt.after @@ -0,0 +1,39 @@ +//PARAM_TYPES: C +trait A { + fun doA() +} + +open class AImpl: A { + override fun doA() { + throw UnsupportedOperationException() + } +} + +trait B { + fun doB() +} + +class C: AImpl(), B { + override fun doA() { + throw UnsupportedOperationException() + } + + override fun doB() { + throw UnsupportedOperationException() + } + + fun doC() { + throw UnsupportedOperationException() + } +} + +// SIBLING: +fun foo(c: C) { + c.doA() + c.doB() + unit(c) +} + +fun unit(c: C) { + c.doC() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy4.kt b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy4.kt new file mode 100644 index 00000000000..e7495780bba --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy4.kt @@ -0,0 +1,35 @@ +//PARAM_TYPES: C +trait A { + fun doA() +} + +open class AImpl: A { + override fun doA() { + throw UnsupportedOperationException() + } +} + +trait B { + fun doB() +} + +class C: AImpl(), B { + override fun doA() { + throw UnsupportedOperationException() + } + + override fun doB() { + throw UnsupportedOperationException() + } + + fun doC() { + throw UnsupportedOperationException() + } +} + +// SIBLING: +fun foo(c: C) { + c.doA() + c.doB() + c.doC() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy4.kt.after b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy4.kt.after new file mode 100644 index 00000000000..75594210f4b --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy4.kt.after @@ -0,0 +1,39 @@ +//PARAM_TYPES: C +trait A { + fun doA() +} + +open class AImpl: A { + override fun doA() { + throw UnsupportedOperationException() + } +} + +trait B { + fun doB() +} + +class C: AImpl(), B { + override fun doA() { + throw UnsupportedOperationException() + } + + override fun doB() { + throw UnsupportedOperationException() + } + + fun doC() { + throw UnsupportedOperationException() + } +} + +// SIBLING: +fun foo(c: C) { + unit(c) + c.doC() +} + +fun unit(c: C) { + c.doA() + c.doB() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitLabeledThisInMember.kt b/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitLabeledThisInMember.kt index 9b793169806..55672bccccd 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitLabeledThisInMember.kt +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitLabeledThisInMember.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: A +// PARAM_TYPES: A.B public open class Z { val z: Int = 0 } diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitLabeledThisInMember.kt.after b/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitLabeledThisInMember.kt.after index 932c04b5a0d..19c2d063532 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitLabeledThisInMember.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitLabeledThisInMember.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: A +// PARAM_TYPES: A.B public open class Z { val z: Int = 0 } diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInExtension.kt b/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInExtension.kt index de578bee1e2..f6aca51d5c7 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInExtension.kt +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInExtension.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: Z class Z(val a: Int) // SIBLING: diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInExtension.kt.after b/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInExtension.kt.after index db4d498bd74..051cb4833e7 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInExtension.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInExtension.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: Z class Z(val a: Int) // SIBLING: @@ -6,5 +7,5 @@ fun Z.foo(): Int { } fun Z.i(): Int { - return a + return this.a } diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInMember.kt b/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInMember.kt index 6bf09f98e4f..c37338507bf 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInMember.kt +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInMember.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: A +// PARAM_TYPES: A.B public open class Z { val z: Int = 0 } diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInMember.kt.after b/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInMember.kt.after index 48d65eb567b..55bb2b0b28b 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInMember.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisInMember.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: A +// PARAM_TYPES: A.B public open class Z { val z: Int = 0 } diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitLabeledThisInMember.kt b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitLabeledThisInMember.kt index a9ef6b95ce9..2d338b4b8fe 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitLabeledThisInMember.kt +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitLabeledThisInMember.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: A +// PARAM_TYPES: A.B public open class Z { val z: Int = 0 } diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitLabeledThisInMember.kt.after b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitLabeledThisInMember.kt.after index 932c04b5a0d..19c2d063532 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitLabeledThisInMember.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitLabeledThisInMember.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: A +// PARAM_TYPES: A.B public open class Z { val z: Int = 0 } diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitThisInExtension.kt b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitThisInExtension.kt index 0946bdd5021..171724d966b 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitThisInExtension.kt +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitThisInExtension.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: Z class Z(val a: Int) // SIBLING: diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitThisInExtension.kt.after b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitThisInExtension.kt.after index 5686b9478dd..16cda1746fc 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitThisInExtension.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitThisInExtension.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: Z class Z(val a: Int) // SIBLING: @@ -6,5 +7,5 @@ fun Z.foo(): Int { } fun Z.i(): Int { - return a + a + return this.a + a } diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInExtension.kt b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInExtension.kt index 51e55077b5a..2a8b91855c5 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInExtension.kt +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInExtension.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: Z class Z(val a: Int) // SIBLING: diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInExtension.kt.after b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInExtension.kt.after index db4d498bd74..9000c97c6a6 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInExtension.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInExtension.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: Z class Z(val a: Int) // SIBLING: diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInMember.kt b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInMember.kt index ed05565e00d..b6f4e488ce9 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInMember.kt +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInMember.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: A +// PARAM_TYPES: A.B public open class Z { val z: Int = 0 } diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInMember.kt.after b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInMember.kt.after index 72160c11655..8c0a5e68db8 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInMember.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisInMember.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: A +// PARAM_TYPES: A.B public open class Z { val z: Int = 0 } diff --git a/idea/testData/refactoring/extractFunction/parameters/it/innerIt.kt b/idea/testData/refactoring/extractFunction/parameters/it/innerIt.kt new file mode 100644 index 00000000000..a78c1a188cc --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/it/innerIt.kt @@ -0,0 +1,9 @@ +// PARAM_TYPES: kotlin.Int +fun Array.check(f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array>) { + if (t.check { it.check{ it + 1 > 1 } }) { + println("OK") + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/it/innerIt.kt.after b/idea/testData/refactoring/extractFunction/parameters/it/innerIt.kt.after new file mode 100644 index 00000000000..68d4a5e2af0 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/it/innerIt.kt.after @@ -0,0 +1,13 @@ +// PARAM_TYPES: kotlin.Int +fun Array.check(f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array>) { + if (t.check { it.check{ i(it) > 1 } }) { + println("OK") + } +} + +fun i(it: Int): Int { + return it + 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/it/lambdaWithIt.kt b/idea/testData/refactoring/extractFunction/parameters/it/lambdaWithIt.kt new file mode 100644 index 00000000000..5e2a55eec06 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/it/lambdaWithIt.kt @@ -0,0 +1,9 @@ +// PARAM_TYPES: kotlin.Array +fun Array.check(f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array) { + if (t.check { it + 1 > 1 }) { + println("OK") + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/it/lambdaWithIt.kt.after b/idea/testData/refactoring/extractFunction/parameters/it/lambdaWithIt.kt.after new file mode 100644 index 00000000000..6aa70ab366d --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/it/lambdaWithIt.kt.after @@ -0,0 +1,13 @@ +// PARAM_TYPES: kotlin.Array +fun Array.check(f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array) { + if (b(t)) { + println("OK") + } +} + +fun b(t: Array): Boolean { + return t.check { it + 1 > 1 } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/it/outerIt.kt b/idea/testData/refactoring/extractFunction/parameters/it/outerIt.kt new file mode 100644 index 00000000000..2022e6452c0 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/it/outerIt.kt @@ -0,0 +1,9 @@ +// PARAM_TYPES: kotlin.Array +fun Array.check(f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array>) { + if (t.check { it.check{ it + 1 > 1 } }) { + println("OK") + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/it/outerIt.kt.after b/idea/testData/refactoring/extractFunction/parameters/it/outerIt.kt.after new file mode 100644 index 00000000000..f5c2eaa5e1b --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/it/outerIt.kt.after @@ -0,0 +1,13 @@ +// PARAM_TYPES: kotlin.Array +fun Array.check(f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array>) { + if (t.check { b(it) }) { + println("OK") + } +} + +fun b(it: Array): Boolean { + return it.check { it + 1 > 1 } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/it/simpleIt.kt b/idea/testData/refactoring/extractFunction/parameters/it/simpleIt.kt new file mode 100644 index 00000000000..a81b51a5574 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/it/simpleIt.kt @@ -0,0 +1,9 @@ +// PARAM_TYPES: kotlin.Int +fun Array.check(f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array) { + if (t.check { it + 1 > 1 }) { + println("OK") + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/it/simpleIt.kt.after b/idea/testData/refactoring/extractFunction/parameters/it/simpleIt.kt.after new file mode 100644 index 00000000000..bcdc0a3349a --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/it/simpleIt.kt.after @@ -0,0 +1,13 @@ +// PARAM_TYPES: kotlin.Int +fun Array.check(f: (T) -> Boolean): Boolean = false + +// SIBLING: +fun foo(t: Array) { + if (t.check { i(it) > 1 }) { + println("OK") + } +} + +fun i(it: Int): Int { + return it + 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/misc/multiDeclaration.kt b/idea/testData/refactoring/extractFunction/parameters/misc/multiDeclaration.kt index e3e6b45d5a7..35c49a8987e 100644 --- a/idea/testData/refactoring/extractFunction/parameters/misc/multiDeclaration.kt +++ b/idea/testData/refactoring/extractFunction/parameters/misc/multiDeclaration.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any // SIBLING: fun main(args: Array) { val (a, b) = Data(1, 2) diff --git a/idea/testData/refactoring/extractFunction/parameters/misc/multiDeclaration.kt.after b/idea/testData/refactoring/extractFunction/parameters/misc/multiDeclaration.kt.after index 6197dc5540b..374ce76203e 100644 --- a/idea/testData/refactoring/extractFunction/parameters/misc/multiDeclaration.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/misc/multiDeclaration.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: kotlin.Int, Number, Comparable, Any // SIBLING: fun main(args: Array) { val (a, b) = Data(1, 2) diff --git a/idea/testData/refactoring/extractFunction/parameters/misc/multipleOccurrences.kt b/idea/testData/refactoring/extractFunction/parameters/misc/multipleOccurrences.kt index 9a876cd41c8..6f824a05a7a 100644 --- a/idea/testData/refactoring/extractFunction/parameters/misc/multipleOccurrences.kt +++ b/idea/testData/refactoring/extractFunction/parameters/misc/multipleOccurrences.kt @@ -1,3 +1,6 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int, b: Int, c: Int): Int { return (a + b*a - c) + b*c diff --git a/idea/testData/refactoring/extractFunction/parameters/misc/multipleOccurrences.kt.after b/idea/testData/refactoring/extractFunction/parameters/misc/multipleOccurrences.kt.after index b82bcb36d27..0a54daa0e54 100644 --- a/idea/testData/refactoring/extractFunction/parameters/misc/multipleOccurrences.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/misc/multipleOccurrences.kt.after @@ -1,3 +1,6 @@ +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: fun foo(a: Int, b: Int, c: Int): Int { return i(a, b, c) diff --git a/idea/testData/refactoring/extractFunction/parameters/misc/usagesInCallArgs.kt b/idea/testData/refactoring/extractFunction/parameters/misc/usagesInCallArgs.kt index 5761a4b2bff..6b381cd32b6 100644 --- a/idea/testData/refactoring/extractFunction/parameters/misc/usagesInCallArgs.kt +++ b/idea/testData/refactoring/extractFunction/parameters/misc/usagesInCallArgs.kt @@ -1,3 +1,7 @@ +// PARAM_TYPES: A +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: public class A() { fun bar(a: Int, b: Int): Int { diff --git a/idea/testData/refactoring/extractFunction/parameters/misc/usagesInCallArgs.kt.after b/idea/testData/refactoring/extractFunction/parameters/misc/usagesInCallArgs.kt.after index 885b558f0a3..4b19703b654 100644 --- a/idea/testData/refactoring/extractFunction/parameters/misc/usagesInCallArgs.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/misc/usagesInCallArgs.kt.after @@ -1,3 +1,7 @@ +// PARAM_TYPES: A +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int +// PARAM_TYPES: kotlin.Int // SIBLING: public class A() { fun bar(a: Int, b: Int): Int { diff --git a/idea/testData/refactoring/extractFunction/parameters/misc/variableAsFunction.kt b/idea/testData/refactoring/extractFunction/parameters/misc/variableAsFunction.kt new file mode 100644 index 00000000000..c2f7f75c3b8 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/misc/variableAsFunction.kt @@ -0,0 +1,9 @@ +// PARAM_TYPES: A +class A { + fun invoke() = 20 +} +// SIBLING: +fun testProp() { + val foo = A() + foo() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/misc/variableAsFunction.kt.after b/idea/testData/refactoring/extractFunction/parameters/misc/variableAsFunction.kt.after new file mode 100644 index 00000000000..565522f7989 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/misc/variableAsFunction.kt.after @@ -0,0 +1,13 @@ +// PARAM_TYPES: A +class A { + fun invoke() = 20 +} +// SIBLING: +fun testProp() { + val foo = A() + unit(foo) +} + +fun unit(foo: A) { + foo() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt index e742a9b01dd..b625943954d 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt +++ b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: V open class Data(val x: Int) class Pair(val a: A, val b: B) diff --git a/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt.after index de2341f088b..d0f22c861d5 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt.after +++ b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameter.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: V open class Data(val x: Int) class Pair(val a: A, val b: B) diff --git a/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt index d5f09c3dc63..32cc2939d3c 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt +++ b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: V open class Data(val x: Int) trait DataEx diff --git a/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt.after index a6e6466e197..0a6fe47d0a8 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt.after +++ b/idea/testData/refactoring/extractFunction/typeParameters/simpleTypeParameterWithConstraint.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: V open class Data(val x: Int) trait DataEx diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt index ceb82dc3794..57e94ee0871 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: Data class Data(val t: Int) // SIBLING: diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt.after index 9cd97061b3f..4a5fe65d03f 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt.after +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParamInArgument.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: Data class Data(val t: Int) // SIBLING: diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt index b0a9f7e494a..40ab68a7289 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt @@ -1,3 +1,6 @@ +// PARAM_TYPES: A +// PARAM_TYPES: A.B +// PARAM_TYPES: V, Data open class Data(val x: Int) trait DataEx trait DataExEx diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt.after index e7dc5965d8a..f5493f70dc8 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt.after +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined1.kt.after @@ -1,3 +1,6 @@ +// PARAM_TYPES: A +// PARAM_TYPES: A.B +// PARAM_TYPES: V, Data open class Data(val x: Int) trait DataEx trait DataExEx diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt index 0802d6e3bf6..1d669a511e8 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: A.B +// PARAM_TYPES: V, Data open class Data(val x: Int) trait DataEx trait DataExEx diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt.after index cea3de19fdd..98ea1f8394c 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt.after +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined2.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: A.B +// PARAM_TYPES: V, Data open class Data(val x: Int) trait DataEx trait DataExEx diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt index 744b08cd3f5..86d701ab736 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: V, Data open class Data(val x: Int) trait DataEx trait DataExEx diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt.after index 1faeda07004..7d12e02d8b2 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt.after +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersAndConstraintsCombined3.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: V, Data open class Data(val x: Int) trait DataEx trait DataExEx diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt index 95b7b5dc375..4b7a69df8c9 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt @@ -1,3 +1,6 @@ +// PARAM_TYPES: A +// PARAM_TYPES: A.B +// PARAM_TYPES: V, Data open class Data(val x: Int) // SIBLING: diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt.after index b8bda4914c7..82c63d9844b 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt.after +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined1.kt.after @@ -1,3 +1,6 @@ +// PARAM_TYPES: A +// PARAM_TYPES: A.B +// PARAM_TYPES: V, Data open class Data(val x: Int) // SIBLING: diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt index 9bbcb0101a0..29f47a485c3 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: A.B +// PARAM_TYPES: V, Data open class Data(val x: Int) class A(val t: T) { diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt.after index fadf4ee100b..7f093f0d6c6 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt.after +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined2.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: A.B +// PARAM_TYPES: V, Data open class Data(val x: Int) class A(val t: T) { diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt index 23422827e45..25804fef6a9 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt @@ -1,3 +1,4 @@ +// PARAM_TYPES: V, Data open class Data(val x: Int) class A(val t: T) { diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt.after index c67966c5ee4..0b63c4e431b 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt.after +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombined3.kt.after @@ -1,3 +1,4 @@ +// PARAM_TYPES: V, Data open class Data(val x: Int) class A(val t: T) { diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt index d32eebe2c14..e2290712601 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt @@ -1,3 +1,5 @@ +// PARAM_TYPES: A +// PARAM_TYPES: V, Data open class Data(val x: Int) trait DataEx diff --git a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt.after b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt.after index 03d814aff07..6f2f7c0681d 100644 --- a/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt.after +++ b/idea/testData/refactoring/extractFunction/typeParameters/typeParametersCombinedAndThis.kt.after @@ -1,3 +1,5 @@ +// PARAM_TYPES: A +// PARAM_TYPES: V, Data open class Data(val x: Int) trait DataEx diff --git a/idea/testData/shortenRefs/imports/leaveQualifiedConstructor.kt b/idea/testData/shortenRefs/imports/leaveQualifiedConstructor.kt new file mode 100644 index 00000000000..0d08370f9a1 --- /dev/null +++ b/idea/testData/shortenRefs/imports/leaveQualifiedConstructor.kt @@ -0,0 +1,4 @@ +// OPTIMIZE_IMPORTS +import java.util.Date + +val x = java.sql.Date(1) diff --git a/idea/testData/shortenRefs/imports/leaveQualifiedConstructor.kt.after b/idea/testData/shortenRefs/imports/leaveQualifiedConstructor.kt.after new file mode 100644 index 00000000000..0bce500e37a --- /dev/null +++ b/idea/testData/shortenRefs/imports/leaveQualifiedConstructor.kt.after @@ -0,0 +1,4 @@ +// OPTIMIZE_IMPORTS +import java.sql.Date + +val x = Date(1) diff --git a/idea/testData/shortenRefs/imports/leaveQualifiedType.kt b/idea/testData/shortenRefs/imports/leaveQualifiedType.kt new file mode 100644 index 00000000000..94bee0a3da3 --- /dev/null +++ b/idea/testData/shortenRefs/imports/leaveQualifiedType.kt @@ -0,0 +1,4 @@ +// OPTIMIZE_IMPORTS +import java.util.Date + +class A : java.sql.Date \ No newline at end of file diff --git a/idea/testData/shortenRefs/imports/leaveQualifiedType.kt.after b/idea/testData/shortenRefs/imports/leaveQualifiedType.kt.after new file mode 100644 index 00000000000..baf93cfc2c9 --- /dev/null +++ b/idea/testData/shortenRefs/imports/leaveQualifiedType.kt.after @@ -0,0 +1,4 @@ +// OPTIMIZE_IMPORTS +import java.sql.Date + +class A : Date \ No newline at end of file diff --git a/idea/testData/shortenRefs/imports/optimizeMultipleImports.kt b/idea/testData/shortenRefs/imports/optimizeMultipleImports.kt new file mode 100644 index 00000000000..7d2b6bb180f --- /dev/null +++ b/idea/testData/shortenRefs/imports/optimizeMultipleImports.kt @@ -0,0 +1,4 @@ +// OPTIMIZE_IMPORTS +import java.io.* + +class A(val d: java.sql.Date, val rs: java.sql.ResultSet) diff --git a/idea/testData/shortenRefs/imports/optimizeMultipleImports.kt.after b/idea/testData/shortenRefs/imports/optimizeMultipleImports.kt.after new file mode 100644 index 00000000000..e421fe4a1e0 --- /dev/null +++ b/idea/testData/shortenRefs/imports/optimizeMultipleImports.kt.after @@ -0,0 +1,5 @@ +// OPTIMIZE_IMPORTS +import java.sql.Date +import java.sql.ResultSet + +class A(val d: Date, val rs: ResultSet) diff --git a/idea/testData/shortenRefs/noShortening.kt b/idea/testData/shortenRefs/noShortening.kt new file mode 100644 index 00000000000..89b75813155 --- /dev/null +++ b/idea/testData/shortenRefs/noShortening.kt @@ -0,0 +1,7 @@ +trait T : Iterable + +abstract class C : T { + fun foo(c: C) { + if (c.any { it.size > 1 }) {} + } +} \ No newline at end of file diff --git a/idea/testData/shortenRefs/noShortening.kt.after b/idea/testData/shortenRefs/noShortening.kt.after new file mode 100644 index 00000000000..bd5285f3b1c --- /dev/null +++ b/idea/testData/shortenRefs/noShortening.kt.after @@ -0,0 +1,7 @@ +trait T : Iterable + +abstract class C : T { + fun foo(c: C) { + if (c.any { it.size > 1 }) {} + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/arrayType.java b/idea/testData/typeSubstitution/arrayType.java new file mode 100644 index 00000000000..63c786d0e79 --- /dev/null +++ b/idea/testData/typeSubstitution/arrayType.java @@ -0,0 +1,8 @@ +interface arrayType { + interface SuperArray { + T[] typeForSubstitute(); + } + + interface MidArray extends SuperArray { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/classType.java b/idea/testData/typeSubstitution/classType.java new file mode 100644 index 00000000000..57fd4b9587d --- /dev/null +++ b/idea/testData/typeSubstitution/classType.java @@ -0,0 +1,8 @@ +interface classType { + interface SuperClass { + List typeForSubstitute(); + } + + interface MidClass extends SuperClass { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/classWithWildcard.java b/idea/testData/typeSubstitution/classWithWildcard.java new file mode 100644 index 00000000000..68e6a144c43 --- /dev/null +++ b/idea/testData/typeSubstitution/classWithWildcard.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface classWithWildcard { + interface SuperList { + List typeForSubstitute(); + } + + interface MidList extends SuperList> { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/genericArray.java b/idea/testData/typeSubstitution/genericArray.java new file mode 100644 index 00000000000..6840d9b0f05 --- /dev/null +++ b/idea/testData/typeSubstitution/genericArray.java @@ -0,0 +1,8 @@ +interface genericArray { + interface SuperGenericArray { + T typeForSubstitute(); + } + + interface MidGenericArray extends SuperGenericArray { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/innerParameter.java b/idea/testData/typeSubstitution/innerParameter.java new file mode 100644 index 00000000000..bd9050093ed --- /dev/null +++ b/idea/testData/typeSubstitution/innerParameter.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface innerParameter { + interface SuperInnerParam { + T typeForSubstitute(); + } + + interface MidInnerParam extends SuperInnerParam { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/intersectionType.java b/idea/testData/typeSubstitution/intersectionType.java new file mode 100644 index 00000000000..4aeaa7c401c --- /dev/null +++ b/idea/testData/typeSubstitution/intersectionType.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface intersectionType { + interface SuperIntersection { + & List> R typeForSubstitute(); + } + + interface MidIntersection extends SuperIntersection { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/intersectionTypeAsTypeParameter.java b/idea/testData/typeSubstitution/intersectionTypeAsTypeParameter.java new file mode 100644 index 00000000000..0a6e5912019 --- /dev/null +++ b/idea/testData/typeSubstitution/intersectionTypeAsTypeParameter.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface intersectionTypeAsTypeParameter { + interface Super { + & List> Map typeForSubstitute(); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/intersectionTypeInEnum.java b/idea/testData/typeSubstitution/intersectionTypeInEnum.java new file mode 100644 index 00000000000..c4f005ce501 --- /dev/null +++ b/idea/testData/typeSubstitution/intersectionTypeInEnum.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface intersectionTypeInEnum { + interface Super { + & List> Enum typeForSubstitute(); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/intersectionTypeInInterfaceDeclaration.java b/idea/testData/typeSubstitution/intersectionTypeInInterfaceDeclaration.java new file mode 100644 index 00000000000..d3984b60dd1 --- /dev/null +++ b/idea/testData/typeSubstitution/intersectionTypeInInterfaceDeclaration.java @@ -0,0 +1,8 @@ +interface intersectionTypeInInterfaceDeclaration { + interface SuperIntersection { + T typeForSubstitute(); + } + + interface MidIntersection extends SuperIntersection { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/intersectionTypeInTypeVariableClass.java b/idea/testData/typeSubstitution/intersectionTypeInTypeVariableClass.java new file mode 100644 index 00000000000..eb6bffbb236 --- /dev/null +++ b/idea/testData/typeSubstitution/intersectionTypeInTypeVariableClass.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface intersectionTypeInTypeVariableClass { + interface Super { + & List> TypeVariable typeForSubstitute(); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/mapEntry.java b/idea/testData/typeSubstitution/mapEntry.java new file mode 100644 index 00000000000..ee711c4596e --- /dev/null +++ b/idea/testData/typeSubstitution/mapEntry.java @@ -0,0 +1,10 @@ +import java.util.Map; + +interface mapEntry { + interface Super { + Map.Entry typeForSubstitute(); + } + + interface Mid extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/primitiveType.java b/idea/testData/typeSubstitution/primitiveType.java new file mode 100644 index 00000000000..e28c8a1808f --- /dev/null +++ b/idea/testData/typeSubstitution/primitiveType.java @@ -0,0 +1,8 @@ +interface primitiveType { + interface SuperPrimitive { + int typeForSubstitute(); + } + + interface MidPrimitive extends SuperPrimitive { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/rawArrayType.java b/idea/testData/typeSubstitution/rawArrayType.java new file mode 100644 index 00000000000..18bc5e67a5c --- /dev/null +++ b/idea/testData/typeSubstitution/rawArrayType.java @@ -0,0 +1,8 @@ +interface rawArrayType { + interface SuperArray { + T[] typeForSubstitute(); + } + + interface MidArray extends SuperArray { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/rawArrayTypeParameterWithBound.java b/idea/testData/typeSubstitution/rawArrayTypeParameterWithBound.java new file mode 100644 index 00000000000..3c97bffd13c --- /dev/null +++ b/idea/testData/typeSubstitution/rawArrayTypeParameterWithBound.java @@ -0,0 +1,8 @@ +interface rawArrayTypeParameterWithBound { + interface Super { + T[] typeForSubstitute(); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/rawEnum.java b/idea/testData/typeSubstitution/rawEnum.java new file mode 100644 index 00000000000..2320cbd9070 --- /dev/null +++ b/idea/testData/typeSubstitution/rawEnum.java @@ -0,0 +1,8 @@ +interface rawEnum { + interface Super> { + Enum typeForSubstitute(); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/rawExtendsWildcard.java b/idea/testData/typeSubstitution/rawExtendsWildcard.java new file mode 100644 index 00000000000..026c9229551 --- /dev/null +++ b/idea/testData/typeSubstitution/rawExtendsWildcard.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface rawExtendsWildcard { + interface SuperRawWild { + List typeForSubstitute(); + } + + interface MidRawWildcard extends SuperRawWild { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/rawIntersectionType.java b/idea/testData/typeSubstitution/rawIntersectionType.java new file mode 100644 index 00000000000..3a568159dcb --- /dev/null +++ b/idea/testData/typeSubstitution/rawIntersectionType.java @@ -0,0 +1,8 @@ +interface rawIntersectionType { + interface Super { + T typeForSubstitute(); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/rawSuperWildcard.java b/idea/testData/typeSubstitution/rawSuperWildcard.java new file mode 100644 index 00000000000..85fb61c8943 --- /dev/null +++ b/idea/testData/typeSubstitution/rawSuperWildcard.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface rawSuperWildcard { + interface SuperRawWild { + List typeForSubstitute(); + } + + interface MidRawWildcard extends SuperRawWild { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/rawType.java b/idea/testData/typeSubstitution/rawType.java new file mode 100644 index 00000000000..f928f813758 --- /dev/null +++ b/idea/testData/typeSubstitution/rawType.java @@ -0,0 +1,8 @@ +interface rawType { + interface Super { + T typeForSubstitute(); + } + + interface MidRaw extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/rawTypeInDeclaration.java b/idea/testData/typeSubstitution/rawTypeInDeclaration.java new file mode 100644 index 00000000000..e912477d946 --- /dev/null +++ b/idea/testData/typeSubstitution/rawTypeInDeclaration.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface rawTypeInDeclaration { + interface Super { + List typeForSubstitute(); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/rawTypeWithBound.java b/idea/testData/typeSubstitution/rawTypeWithBound.java new file mode 100644 index 00000000000..e96a9e36bf4 --- /dev/null +++ b/idea/testData/typeSubstitution/rawTypeWithBound.java @@ -0,0 +1,8 @@ +interface rawTypeWithBound { + interface Super { + T typeForSubstitute(); + } + + interface MidRaw extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/rawTypeWithSelfReferenceBound.java b/idea/testData/typeSubstitution/rawTypeWithSelfReferenceBound.java new file mode 100644 index 00000000000..e8375c373e8 --- /dev/null +++ b/idea/testData/typeSubstitution/rawTypeWithSelfReferenceBound.java @@ -0,0 +1,8 @@ +interface rawTypeWithSelfReferenceBound { + interface Super> { + T typeForSubstitute(); + } + + interface MidRaw extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/rawWildcardInTypeVariableClass.java b/idea/testData/typeSubstitution/rawWildcardInTypeVariableClass.java new file mode 100644 index 00000000000..6d4c7a75042 --- /dev/null +++ b/idea/testData/typeSubstitution/rawWildcardInTypeVariableClass.java @@ -0,0 +1,10 @@ +import java.lang.reflect.TypeVariable; + +interface rawWildcardInTypeVariableClass { + interface Super { + TypeVariable typeForSubstitute(); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/rawWildcardWithBound.java b/idea/testData/typeSubstitution/rawWildcardWithBound.java new file mode 100644 index 00000000000..fba6ef0157a --- /dev/null +++ b/idea/testData/typeSubstitution/rawWildcardWithBound.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface rawWildcardWithBound { + interface Super { + List typeForSubstitute(); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/selfReference.java b/idea/testData/typeSubstitution/selfReference.java new file mode 100644 index 00000000000..c6958f1e916 --- /dev/null +++ b/idea/testData/typeSubstitution/selfReference.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface selfReference { + interface SuperSelfRef> { + public List typeForSubstitute(); + } + + interface MidSelfRef extends SuperSelfRef { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/twoParameters.java b/idea/testData/typeSubstitution/twoParameters.java new file mode 100644 index 00000000000..d4508cd37d5 --- /dev/null +++ b/idea/testData/typeSubstitution/twoParameters.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface twoParameters { + interface SuperTwoParams { + Map> typeForSubstitute(); + } + + interface MidTwoParams extends SuperTwoParams { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/twoParametersInSubClass.java b/idea/testData/typeSubstitution/twoParametersInSubClass.java new file mode 100644 index 00000000000..579cbfc3b8a --- /dev/null +++ b/idea/testData/typeSubstitution/twoParametersInSubClass.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface twoParametersInSubClass { + interface SuperTwoParams { + List typeForSubstitute(); + } + + interface MidTwoParams extends SuperTwoParams { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/typeVariableClass.java b/idea/testData/typeSubstitution/typeVariableClass.java new file mode 100644 index 00000000000..b738ab5e1b3 --- /dev/null +++ b/idea/testData/typeSubstitution/typeVariableClass.java @@ -0,0 +1,10 @@ +import java.lang.reflect.TypeVariable; + +interface typeVariableClass { + interface Super { + TypeVariable typeForSubstitute(); + } + + interface Mid extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/typeVariableRaw.java b/idea/testData/typeSubstitution/typeVariableRaw.java new file mode 100644 index 00000000000..37464247d2c --- /dev/null +++ b/idea/testData/typeSubstitution/typeVariableRaw.java @@ -0,0 +1,10 @@ +import java.lang.reflect.TypeVariable; + +interface typeVariableRaw { + interface Super { + TypeVariable typeForSubstitute(); + } + + interface Mid extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/unboundedWildcard.java b/idea/testData/typeSubstitution/unboundedWildcard.java new file mode 100644 index 00000000000..232230bf9d4 --- /dev/null +++ b/idea/testData/typeSubstitution/unboundedWildcard.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface unboundedWildcard { + interface Super { + List typeForSubstitute(); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/unboundedWildcardToTypeParameter.java b/idea/testData/typeSubstitution/unboundedWildcardToTypeParameter.java new file mode 100644 index 00000000000..981d5adf796 --- /dev/null +++ b/idea/testData/typeSubstitution/unboundedWildcardToTypeParameter.java @@ -0,0 +1,8 @@ +import java.util.*; + +interface unboundedWildcardToTypeParameter { + interface SupList extends List { + @Override + boolean retainAll(Collection c); // error, check that we do not fall + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/varargArray.java b/idea/testData/typeSubstitution/varargArray.java new file mode 100644 index 00000000000..853db136a2c --- /dev/null +++ b/idea/testData/typeSubstitution/varargArray.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface varargArray { + interface Super { + void typeForSubstitute(T... a); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/varargArrayTypeParameter.java b/idea/testData/typeSubstitution/varargArrayTypeParameter.java new file mode 100644 index 00000000000..0343a15100c --- /dev/null +++ b/idea/testData/typeSubstitution/varargArrayTypeParameter.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface varargArrayTypeParameter { + interface Super { + void typeForSubstitute(T... a); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/varargClass.java b/idea/testData/typeSubstitution/varargClass.java new file mode 100644 index 00000000000..371b6d1226e --- /dev/null +++ b/idea/testData/typeSubstitution/varargClass.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface varargClass { + interface Super { + void typeForSubstitute(List... a); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/varargClassWithWildcard.java b/idea/testData/typeSubstitution/varargClassWithWildcard.java new file mode 100644 index 00000000000..3aa87dfda7d --- /dev/null +++ b/idea/testData/typeSubstitution/varargClassWithWildcard.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface varargClassWithWildcard { + interface Super { + void typeForSubstitute(List... a); + } + + interface Sub extends Super> { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/varargRawType.java b/idea/testData/typeSubstitution/varargRawType.java new file mode 100644 index 00000000000..78a6b2515b2 --- /dev/null +++ b/idea/testData/typeSubstitution/varargRawType.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface varargRawType { + interface Super { + void typeForSubstitute(T... a); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/varargRawTypeWithBound.java b/idea/testData/typeSubstitution/varargRawTypeWithBound.java new file mode 100644 index 00000000000..cc7f8e8fb8b --- /dev/null +++ b/idea/testData/typeSubstitution/varargRawTypeWithBound.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface varargRawTypeWithBound { + interface Super { + void typeForSubstitute(T... a); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/varargToClass.java b/idea/testData/typeSubstitution/varargToClass.java new file mode 100644 index 00000000000..7132de49e80 --- /dev/null +++ b/idea/testData/typeSubstitution/varargToClass.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface varargToClass { + interface Super { + void typeForSubstitute(T... a); + } + + interface Sub extends Super { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/varargToClassWithWildcard.java b/idea/testData/typeSubstitution/varargToClassWithWildcard.java new file mode 100644 index 00000000000..93dc3b520af --- /dev/null +++ b/idea/testData/typeSubstitution/varargToClassWithWildcard.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface varargToClassWithWildcard { + interface Super { + void typeForSubstitute(T... a); + } + + interface Sub extends Super> { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/wildcardExtends.java b/idea/testData/typeSubstitution/wildcardExtends.java new file mode 100644 index 00000000000..721942f6376 --- /dev/null +++ b/idea/testData/typeSubstitution/wildcardExtends.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface wildcardExtends { + interface SuperWildcardExtends { + List typeForSubstitute(); + } + + interface MidWildcardExtends extends SuperWildcardExtends { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/wildcardExtendsObject.java b/idea/testData/typeSubstitution/wildcardExtendsObject.java new file mode 100644 index 00000000000..40e18ca5a83 --- /dev/null +++ b/idea/testData/typeSubstitution/wildcardExtendsObject.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface wildcardExtendsObject { + interface SuperWildcardExtendsObject { + List typeForSubstitute(); + } + + interface MidWildcardExtendsObject extends SuperWildcardExtendsObject { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/wildcardExtendsTypeParameter.java b/idea/testData/typeSubstitution/wildcardExtendsTypeParameter.java new file mode 100644 index 00000000000..d62939b11f3 --- /dev/null +++ b/idea/testData/typeSubstitution/wildcardExtendsTypeParameter.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface wildcardExtendsTypeParameter { + interface SuperWildcard { + Map typeForSubstitute(); + } + + interface MidWildcard extends SuperWildcard { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/wildcardSuper.java b/idea/testData/typeSubstitution/wildcardSuper.java new file mode 100644 index 00000000000..b1342fb7f1f --- /dev/null +++ b/idea/testData/typeSubstitution/wildcardSuper.java @@ -0,0 +1,10 @@ +import java.util.*; + +interface wildcardSuper { + interface SuperWildcardSuper { + List typeForSubstitute(); + } + + interface MidWildcardSuper extends SuperWildcardSuper { + } +} \ No newline at end of file diff --git a/idea/testData/typeSubstitution/wildcardToWildcard.java b/idea/testData/typeSubstitution/wildcardToWildcard.java new file mode 100644 index 00000000000..d52b18dd53c --- /dev/null +++ b/idea/testData/typeSubstitution/wildcardToWildcard.java @@ -0,0 +1,8 @@ +import java.util.*; + +interface wildcardToWildcard { + interface SupList extends List { + @Override + boolean addAll(Collection c); + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/lang/resolve/java/AbstractJavaTypeSubstitutorTest.java b/idea/tests/org/jetbrains/jet/lang/resolve/java/AbstractJavaTypeSubstitutorTest.java new file mode 100644 index 00000000000..fb0dffc21ef --- /dev/null +++ b/idea/tests/org/jetbrains/jet/lang/resolve/java/AbstractJavaTypeSubstitutorTest.java @@ -0,0 +1,115 @@ +/* + * 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.resolve.java; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.testFramework.LightProjectDescriptor; +import org.jetbrains.annotations.NotNull; +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.JavaTypeParameter; +import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaTypeImpl; +import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaTypeParameterImpl; +import org.jetbrains.jet.plugin.JetLightCodeInsightFixtureTestCase; +import org.jetbrains.jet.plugin.JetLightProjectDescriptor; + +public abstract class AbstractJavaTypeSubstitutorTest extends JetLightCodeInsightFixtureTestCase { + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JetLightProjectDescriptor.INSTANCE; + } + + public void doTest(@NotNull String testFile) { + PsiFile psiFile = myFixture.configureByFile(testFile); + + Project project = myFixture.getProject(); + String javaClassName = psiFile.getName().substring(0, psiFile.getName().length() - ".java".length()); + PsiClass psiClass = JavaPsiFacade.getInstance(project).findClass(javaClassName, GlobalSearchScope.allScope(project)); + assert psiClass != null : "Wrong path to test file: " + testFile; + + assert psiClass.getInnerClasses().length > 0; + + for (PsiClass innerInterface : psiClass.getInnerClasses()) { + PsiMethod method = getMethodWithTestData(innerInterface); + + PsiClassType[] superTypes = innerInterface.getSuperTypes(); + for (PsiClassType superType : superTypes) { + if (method.getReturnType() != null) { + doTest(superType, method.getReturnType()); + } + if (method.getTypeParameters().length > 0) { + doTest(superType, method.getTypeParameters()[0]); + } + PsiParameter[] parameters = method.getParameterList().getParameters(); + if (parameters.length > 0) { + doTest(superType, parameters[0].getType()); + } + } + } + } + + private static void doTest(@NotNull PsiClassType type, @NotNull PsiTypeParameter typeParameter) { + PsiType expectedType = type.resolveGenerics().getSubstitutor().substitute(typeParameter); + + JavaClassifierType javaClassifierType = (JavaClassifierType) JavaTypeImpl.create(type); + JavaTypeParameter javaTypeToSubstitute = new JavaTypeParameterImpl(typeParameter); + JavaType actualType = javaClassifierType.getSubstitutor().substitute(javaTypeToSubstitute); + + if (actualType == null) { + assertEquals(expectedType, null); + } + else { + assertEquals(expectedType, ((JavaTypeImpl) actualType).getPsi()); + } + } + + private static void doTest(@NotNull PsiClassType type, @NotNull PsiType psiTypeToSubstitute) { + PsiType expectedType = type.resolveGenerics().getSubstitutor().substitute(psiTypeToSubstitute); + + JavaClassifierType javaClassifierType = (JavaClassifierType) JavaTypeImpl.create(type); + JavaType javaTypeToSubstitute = JavaTypeImpl.create(psiTypeToSubstitute); + JavaType actualType = javaClassifierType.getSubstitutor().substitute(javaTypeToSubstitute); + + if (expectedType instanceof PsiEllipsisType) { + PsiEllipsisType ellipsisType = (PsiEllipsisType) expectedType; + assertEquals(ellipsisType.toArrayType(), ((JavaTypeImpl) actualType).getPsi()); + } + else { + assertEquals(expectedType, ((JavaTypeImpl) actualType).getPsi()); + } + } + + @NotNull + private static PsiMethod getMethodWithTestData(@NotNull PsiClass psiClass) { + String substituteParameterName = "typeForSubstitute"; + PsiMethod[] methods = psiClass.findMethodsByName(substituteParameterName, false); + if (methods.length == 0) { + methods = psiClass.findMethodsByName(substituteParameterName, true); + } + + if (methods.length == 0) { + methods = psiClass.getMethods(); + } + + assert methods.length > 0 : "Wrong parameters for test: method typeForSubstitute not found"; + + return methods[0]; + } +} diff --git a/idea/tests/org/jetbrains/jet/lang/resolve/java/JavaTypeSubstitutorTestGenerated.java b/idea/tests/org/jetbrains/jet/lang/resolve/java/JavaTypeSubstitutorTestGenerated.java new file mode 100644 index 00000000000..0e101962a12 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/lang/resolve/java/JavaTypeSubstitutorTestGenerated.java @@ -0,0 +1,259 @@ +/* + * 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.resolve.java; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestSuite; + +import java.io.File; +import java.util.regex.Pattern; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.test.InnerTestClasses; +import org.jetbrains.jet.test.TestMetadata; + +import org.jetbrains.jet.lang.resolve.java.AbstractJavaTypeSubstitutorTest; + +/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/testData/typeSubstitution") +public class JavaTypeSubstitutorTestGenerated extends AbstractJavaTypeSubstitutorTest { + public void testAllFilesPresentInTypeSubstitution() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/typeSubstitution"), Pattern.compile("^(.+)\\.java$"), true); + } + + @TestMetadata("arrayType.java") + public void testArrayType() throws Exception { + doTest("idea/testData/typeSubstitution/arrayType.java"); + } + + @TestMetadata("classType.java") + public void testClassType() throws Exception { + doTest("idea/testData/typeSubstitution/classType.java"); + } + + @TestMetadata("classWithWildcard.java") + public void testClassWithWildcard() throws Exception { + doTest("idea/testData/typeSubstitution/classWithWildcard.java"); + } + + @TestMetadata("genericArray.java") + public void testGenericArray() throws Exception { + doTest("idea/testData/typeSubstitution/genericArray.java"); + } + + @TestMetadata("innerParameter.java") + public void testInnerParameter() throws Exception { + doTest("idea/testData/typeSubstitution/innerParameter.java"); + } + + @TestMetadata("intersectionType.java") + public void testIntersectionType() throws Exception { + doTest("idea/testData/typeSubstitution/intersectionType.java"); + } + + @TestMetadata("intersectionTypeAsTypeParameter.java") + public void testIntersectionTypeAsTypeParameter() throws Exception { + doTest("idea/testData/typeSubstitution/intersectionTypeAsTypeParameter.java"); + } + + @TestMetadata("intersectionTypeInEnum.java") + public void testIntersectionTypeInEnum() throws Exception { + doTest("idea/testData/typeSubstitution/intersectionTypeInEnum.java"); + } + + @TestMetadata("intersectionTypeInInterfaceDeclaration.java") + public void testIntersectionTypeInInterfaceDeclaration() throws Exception { + doTest("idea/testData/typeSubstitution/intersectionTypeInInterfaceDeclaration.java"); + } + + @TestMetadata("intersectionTypeInTypeVariableClass.java") + public void testIntersectionTypeInTypeVariableClass() throws Exception { + doTest("idea/testData/typeSubstitution/intersectionTypeInTypeVariableClass.java"); + } + + @TestMetadata("mapEntry.java") + public void testMapEntry() throws Exception { + doTest("idea/testData/typeSubstitution/mapEntry.java"); + } + + @TestMetadata("primitiveType.java") + public void testPrimitiveType() throws Exception { + doTest("idea/testData/typeSubstitution/primitiveType.java"); + } + + @TestMetadata("rawArrayType.java") + public void testRawArrayType() throws Exception { + doTest("idea/testData/typeSubstitution/rawArrayType.java"); + } + + @TestMetadata("rawArrayTypeParameterWithBound.java") + public void testRawArrayTypeParameterWithBound() throws Exception { + doTest("idea/testData/typeSubstitution/rawArrayTypeParameterWithBound.java"); + } + + @TestMetadata("rawEnum.java") + public void testRawEnum() throws Exception { + doTest("idea/testData/typeSubstitution/rawEnum.java"); + } + + @TestMetadata("rawExtendsWildcard.java") + public void testRawExtendsWildcard() throws Exception { + doTest("idea/testData/typeSubstitution/rawExtendsWildcard.java"); + } + + @TestMetadata("rawIntersectionType.java") + public void testRawIntersectionType() throws Exception { + doTest("idea/testData/typeSubstitution/rawIntersectionType.java"); + } + + @TestMetadata("rawSuperWildcard.java") + public void testRawSuperWildcard() throws Exception { + doTest("idea/testData/typeSubstitution/rawSuperWildcard.java"); + } + + @TestMetadata("rawType.java") + public void testRawType() throws Exception { + doTest("idea/testData/typeSubstitution/rawType.java"); + } + + @TestMetadata("rawTypeInDeclaration.java") + public void testRawTypeInDeclaration() throws Exception { + doTest("idea/testData/typeSubstitution/rawTypeInDeclaration.java"); + } + + @TestMetadata("rawTypeWithBound.java") + public void testRawTypeWithBound() throws Exception { + doTest("idea/testData/typeSubstitution/rawTypeWithBound.java"); + } + + @TestMetadata("rawTypeWithSelfReferenceBound.java") + public void testRawTypeWithSelfReferenceBound() throws Exception { + doTest("idea/testData/typeSubstitution/rawTypeWithSelfReferenceBound.java"); + } + + @TestMetadata("rawWildcardInTypeVariableClass.java") + public void testRawWildcardInTypeVariableClass() throws Exception { + doTest("idea/testData/typeSubstitution/rawWildcardInTypeVariableClass.java"); + } + + @TestMetadata("rawWildcardWithBound.java") + public void testRawWildcardWithBound() throws Exception { + doTest("idea/testData/typeSubstitution/rawWildcardWithBound.java"); + } + + @TestMetadata("selfReference.java") + public void testSelfReference() throws Exception { + doTest("idea/testData/typeSubstitution/selfReference.java"); + } + + @TestMetadata("twoParameters.java") + public void testTwoParameters() throws Exception { + doTest("idea/testData/typeSubstitution/twoParameters.java"); + } + + @TestMetadata("twoParametersInSubClass.java") + public void testTwoParametersInSubClass() throws Exception { + doTest("idea/testData/typeSubstitution/twoParametersInSubClass.java"); + } + + @TestMetadata("typeVariableClass.java") + public void testTypeVariableClass() throws Exception { + doTest("idea/testData/typeSubstitution/typeVariableClass.java"); + } + + @TestMetadata("typeVariableRaw.java") + public void testTypeVariableRaw() throws Exception { + doTest("idea/testData/typeSubstitution/typeVariableRaw.java"); + } + + @TestMetadata("unboundedWildcard.java") + public void testUnboundedWildcard() throws Exception { + doTest("idea/testData/typeSubstitution/unboundedWildcard.java"); + } + + @TestMetadata("unboundedWildcardToTypeParameter.java") + public void testUnboundedWildcardToTypeParameter() throws Exception { + doTest("idea/testData/typeSubstitution/unboundedWildcardToTypeParameter.java"); + } + + @TestMetadata("varargArray.java") + public void testVarargArray() throws Exception { + doTest("idea/testData/typeSubstitution/varargArray.java"); + } + + @TestMetadata("varargArrayTypeParameter.java") + public void testVarargArrayTypeParameter() throws Exception { + doTest("idea/testData/typeSubstitution/varargArrayTypeParameter.java"); + } + + @TestMetadata("varargClass.java") + public void testVarargClass() throws Exception { + doTest("idea/testData/typeSubstitution/varargClass.java"); + } + + @TestMetadata("varargClassWithWildcard.java") + public void testVarargClassWithWildcard() throws Exception { + doTest("idea/testData/typeSubstitution/varargClassWithWildcard.java"); + } + + @TestMetadata("varargRawType.java") + public void testVarargRawType() throws Exception { + doTest("idea/testData/typeSubstitution/varargRawType.java"); + } + + @TestMetadata("varargRawTypeWithBound.java") + public void testVarargRawTypeWithBound() throws Exception { + doTest("idea/testData/typeSubstitution/varargRawTypeWithBound.java"); + } + + @TestMetadata("varargToClass.java") + public void testVarargToClass() throws Exception { + doTest("idea/testData/typeSubstitution/varargToClass.java"); + } + + @TestMetadata("varargToClassWithWildcard.java") + public void testVarargToClassWithWildcard() throws Exception { + doTest("idea/testData/typeSubstitution/varargToClassWithWildcard.java"); + } + + @TestMetadata("wildcardExtends.java") + public void testWildcardExtends() throws Exception { + doTest("idea/testData/typeSubstitution/wildcardExtends.java"); + } + + @TestMetadata("wildcardExtendsObject.java") + public void testWildcardExtendsObject() throws Exception { + doTest("idea/testData/typeSubstitution/wildcardExtendsObject.java"); + } + + @TestMetadata("wildcardExtendsTypeParameter.java") + public void testWildcardExtendsTypeParameter() throws Exception { + doTest("idea/testData/typeSubstitution/wildcardExtendsTypeParameter.java"); + } + + @TestMetadata("wildcardSuper.java") + public void testWildcardSuper() throws Exception { + doTest("idea/testData/typeSubstitution/wildcardSuper.java"); + } + + @TestMetadata("wildcardToWildcard.java") + public void testWildcardToWildcard() throws Exception { + doTest("idea/testData/typeSubstitution/wildcardToWildcard.java"); + } + +} diff --git a/idea/tests/org/jetbrains/jet/plugin/DirectiveBasedActionUtils.java b/idea/tests/org/jetbrains/jet/plugin/DirectiveBasedActionUtils.java index 4e2d3ec5891..f88c1db30ff 100644 --- a/idea/tests/org/jetbrains/jet/plugin/DirectiveBasedActionUtils.java +++ b/idea/tests/org/jetbrains/jet/plugin/DirectiveBasedActionUtils.java @@ -23,6 +23,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Ordering; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.testFramework.UsefulTestCase; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.InTextDirectivesUtils; import org.jetbrains.jet.lang.diagnostics.Diagnostic; @@ -31,6 +32,7 @@ import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage; import org.jetbrains.jet.plugin.highlighter.IdeErrorMessages; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -82,6 +84,26 @@ public class DirectiveBasedActionUtils { }))); UsefulTestCase.assertOrderedEquals("Some unexpected actions available at current position: %s. Use // ACTION: directive", - actualActions, validActions); + filterOutIrrelevantActions(actualActions), filterOutIrrelevantActions(validActions)); } + + @NotNull + //TODO: hack, implemented because irrelevant actions behave in different ways on build server and locally + // this behaviour should be investigated and hack can be removed + private static Collection filterOutIrrelevantActions(@NotNull Collection actions) { + return Collections2.filter(actions, new Predicate() { + @Override + public boolean apply(String input) { + for (String prefix : IRRELEVANT_ACTION_PREFIXES) { + if (input.startsWith(prefix)) { + return false; + } + } + return true; + } + }); + } + + private static final Collection IRRELEVANT_ACTION_PREFIXES = + Arrays.asList("Disable ", "Edit intention settings", "Edit inspection profile setting"); } diff --git a/idea/tests/org/jetbrains/jet/plugin/codeInsight/OverrideImplementTest.java b/idea/tests/org/jetbrains/jet/plugin/codeInsight/OverrideImplementTest.java index ff051f8b675..418f1711ae3 100644 --- a/idea/tests/org/jetbrains/jet/plugin/codeInsight/OverrideImplementTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/codeInsight/OverrideImplementTest.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.plugin.codeInsight; +import com.intellij.codeInsight.CodeInsightSettings; import org.jetbrains.jet.plugin.PluginTestCaseBase; public final class OverrideImplementTest extends AbstractOverrideImplementTest { @@ -146,6 +147,17 @@ public final class OverrideImplementTest extends AbstractOverrideImplementTest { doImplementDirectoryTest(); } + public void testCheckNotImportedTypesFromJava() { + boolean oldValue = CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY; + try { + CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY = true; + doImplementDirectoryTest(); + } + finally { + CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY = oldValue; + } + } + public void testOverrideSamAdapters() { doOverrideDirectoryTest("foo"); } diff --git a/idea/tests/org/jetbrains/jet/plugin/codeInsight/smartEnter/SmartEnterTest.kt b/idea/tests/org/jetbrains/jet/plugin/codeInsight/smartEnter/SmartEnterTest.kt new file mode 100644 index 00000000000..72e0c45a850 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/codeInsight/smartEnter/SmartEnterTest.kt @@ -0,0 +1,1016 @@ +/* + * 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.plugin.codeInsight.smartEnter + +import org.jetbrains.jet.plugin.JetLightCodeInsightFixtureTestCase +import com.intellij.openapi.actionSystem.IdeActions +import org.jetbrains.jet.plugin.JetFileType +import org.jetbrains.jet.test.util.trimIndent +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase + +class SmartEnterTest : JetLightCodeInsightFixtureTestCase() { + fun testIfCondition() = doFunTest( + """ + if + """ + , + """ + if () { + } + """ + ) + + fun testIfCondition2() = doFunTest( + """ + if + """ + , + """ + if () { + } + """ + ) + + fun testIfWithFollowingCode() = doFunTest( + """ + if + + return true + """ + , + """ + if () { + } + + return true + """ + ) + + fun testIfCondition3() = doFunTest( + """ + if ( + """ + , + """ + if () { + } + """ + ) + + fun testIfCondition4() = doFunTest( + """ + if (true) { + } + """ + , + """ + if (true) { + + } + """ + ) + + fun testIfCondition5() = doFunTest( + """ + if (true) { + """ + , + """ + if (true) { + + } + """ + ) + + fun testIfCondition6() = doFunTest( + """ + if (true) { + println() + } + """ + , + """ + if (true) { + + println() + } + """ + ) + + fun testIfThenOneLine1() = doFunTest( + """ + if (true) println() + """ + , + """ + if (true) println() + + """ + ) + + fun testIfThenOneLine2() = doFunTest( + """ + if (true) println() + """ + , + """ + if (true) println() + + """ + ) + + fun testIfThenMultiLine1() = doFunTest( + """ + if (true) + println() + """ + , + """ + if (true) + println() + + """ + ) + + fun testIfThenMultiLine2() = doFunTest( + """ + if (true) + println() + """ + , + """ + if (true) + println() + + """ + ) + + // TODO: indent for println + fun testIfThenMultiLine3() = doFunTest( + """ + if (true) + println() + """ + , + """ + if (true) { + + } + println() + """ + ) + + fun testIfWithReformat() = doFunTest( + """ + if (true) { + } + """, + """ + if (true) { + + } + """ + ) + + fun testElse() = doFunTest( + """ + if (true) { + } else + """, + """ + if (true) { + } else { + + } + """ + ) + + fun testElseOneLine1() = doFunTest( + """ + if (true) { + } else println() + """, + """ + if (true) { + } else println() + + """ + ) + + fun testElseOneLine2() = doFunTest( + """ + if (true) { + } else println() + """, + """ + if (true) { + } else println() + + """ + ) + + fun testElseTwoLines1() = doFunTest( + """ + if (true) { + } else + println() + """, + """ + if (true) { + } else + println() + + """ + ) + + fun testElseTwoLines2() = doFunTest( + """ + if (true) { + } else + println() + """, + """ + if (true) { + } else + println() + + """ + ) + + // TODO: remove space in expected data + fun testElseWithSpace() = doFunTest( + """ + if (true) { + } else + """, + """ + if (true) { + } else { + + }${' '} + """ + ) + + + fun testWhile() = doFunTest( + """ + while + """ + , + """ + while () { + } + """ + ) + + fun testWhile2() = doFunTest( + """ + while + """ + , + """ + while () { + } + """ + ) + + fun testWhile3() = doFunTest( + """ + while ( + """ + , + """ + while () { + } + """ + ) + + fun testWhile4() = doFunTest( + """ + while (true) { + } + """ + , + """ + while (true) { + + } + """ + ) + + fun testWhile5() = doFunTest( + """ + while (true) { + """ + , + """ + while (true) { + + } + """ + ) + + fun testWhile6() = doFunTest( + """ + while (true) { + println() + } + """ + , + """ + while (true) { + + println() + } + """ + ) + + fun testWhile7() = doFunTest( + """ + while () + """, + """ + while () { + } + """ + ) + + fun testWhileSingle() = doFunTest( + """ + while (true) println() + """, + """ + while (true) println() + + """ + ) + + fun testWhileMultiLine1() = doFunTest( + """ + while (true) + println() + """, + """ + while (true) + println() + + """ + ) + + fun testWhileMultiLine2() = doFunTest( + """ + while (true) + println() + """, + """ + while (true) { + + } + println() + """ + ) + + fun testForStatement() = doFunTest( + """ + for + """ + , + """ + for () { + } + """ + ) + + fun testForStatement2() = doFunTest( + """ + for + """ + , + """ + for () { + } + """ + ) + + fun testForStatement4() = doFunTest( + """ + for (i in 1..10) { + } + """ + , + """ + for (i in 1..10) { + + } + """ + ) + + fun testForStatement5() = doFunTest( + """ + for (i in 1..10) { + """ + , + """ + for (i in 1..10) { + + } + """ + ) + + fun testForStatement6() = doFunTest( + """ + for (i in 1..10) { + println() + } + """ + , + """ + for (i in 1..10) { + + println() + } + """ + ) + + fun testForStatementSingle() = doFunTest( + """ + for (i in 1..10) println() + """ + , + """ + for (i in 1..10) println() + + """ + ) + + fun testForStatementSingleEmpty() = doFunTest( + """ + for () println() + """ + , + """ + for () println() + """ + ) + + fun testForStatementOnLoopParameter() = doFunTest( + """ + for (some) + println() + """ + , + """ + for (some) { + + } + println() + """ + ) + + fun testForMultiLine1() = doFunTest( + """ + for (i in 1..10) + println() + """, + """ + for (i in 1..10) { + + } + println() + """ + ) + + fun testForMultiLine2() = doFunTest( + """ + for (i in 1..10) + println() + """, + """ + for (i in 1..10) + println() + + """ + ) + + fun testWhen() = doFunTest( + """ + when + """ + , + """ + when { + + } + """ + ) + + fun testWhen1() = doFunTest( + """ + when + """ + , + """ + when { + + } + """ + ) + + fun testWhen2() = doFunTest( + """ + when (true) { + } + """ + , + """ + when (true) { + + } + """ + ) + + fun testWhen3() = doFunTest( + """ + when (true) { + """ + , + """ + when (true) { + + } + """ + ) + + fun testWhen4() = doFunTest( + """ + when (true) { + false -> println("false") + } + """ + , + """ + when (true) { + + false -> println("false") + } + """ + ) + + fun testWhen5() = doFunTest( + """ + when () + """ + , + """ + when () { + } + """ + ) + + fun testWhen6() = doFunTest( + """ + when (true) + """ + , + """ + when (true) { + + } + """ + ) + + // Check that no addition {} inserted + fun testWhenBadParsed() = doFunTest( + """ + when ( { + } + """ + , + """ + when ( { + + } + """ + ) + + fun testDoWhile() = doFunTest( + """ + do + """ + , + """ + do { + } while ()${' '} + """ + ) + + fun testDoWhile2() = doFunTest( + """ + do + """ + , + """ + do { + } while () + """ + ) + + fun testDoWhile3() = doFunTest( + """ + do { + println(hi) + } + """ + , + """ + do { + println(hi) + } while () + """ + ) + + fun testDoWhile5() = doFunTest( + """ + do { + } while () + """ + , + """ + do { + } while () + """ + ) + + fun testDoWhile6() = doFunTest( + """ + do { + } while (true) + """ + , + """ + do { + + } while (true) + """ + ) + + fun testDoWhile7() = doFunTest( + """ + do { + } while (true) + """ + , + """ + do { + } while (true) + + """ + ) + + fun testDoWhile8() = doFunTest( + """ + do { + } while (true) + """ + , + """ + do { + + } while (true) + """ + ) + + fun testDoWhile9() = doFunTest( + """ + do while + """ + , + """ + do { + } while () + """ + ) + + fun testDoWhile10() = doFunTest( + """ + do while (true) + """ + , + """ + do { + + } while (true) + """ + ) + + fun testDoWhile11() = doFunTest( + """ + do { + println("some") + } while + """ + , + """ + do { + println("some") + } while () + """ + ) + + fun testDoWhile12() = doFunTest( + """ + do { + println("some") + } while (true + """ + , + """ + do { + + println("some") + } while (true + """ + ) + + fun testDoWhileOneLine1() = doFunTest( + """ + do println("some") while (true) + println("hi") + """ + , + """ + do println("some") while (true) + + println("hi") + """ + ) + + fun testDoWhileOneLine2() = doFunTest( + """ + do println("some") while (true) + println("hi") + """ + , + """ + do println("some") while (true) + + println("hi") + """ + ) + + fun testDoWhileMultiLine1() = doFunTest( + """ + do + println() + while (true) + """, + """ + do + println() + + while (true) + """ + ) + + fun testDoWhileMultiLine2() = doFunTest( + """ + do + println() + while (true) + """, + """ + do { + + println() + } while (true) + """ + ) + + fun testDoWhileMultiLine3() = doFunTest( + """ + do + println() + while (true) + """, + """ + do { + + println() + } while (true) + """ + ) + + fun testFunBody() = doFileTest( + """ + fun test() + """ + , + """ + fun test() { + + } + """ + ) + + fun testFunBody1() = doFileTest( + """ + fun test + """ + , + """ + fun test() { + + } + """ + ) + + fun testFunBody2() = doFileTest( + """ + fun (p: Int, s: String + """ + , + """ + fun (p: Int, s: String) { + + } + """ + ) + + fun testFunBody3() = doFileTest( + """ + trait Some { + fun (p: Int) + } + """ + , + """ + trait Some { + fun (p: Int) + + } + """ + ) + + fun testFunBody4() = doFileTest( + """ + class Some { + abstract fun (p: Int) + } + """ + , + """ + class Some { + abstract fun (p: Int) + + } + """ + ) + + fun testFunBody5() = doFileTest( + """ + class Some { + fun test(p: Int) = 1 + } + """ + , + """ + class Some { + fun test(p: Int) = 1 + + } + """ + ) + + fun testFunBody6() = doFileTest( + """ + fun test(p: Int) { + } + """ + , + """ + fun test(p: Int) { + + } + """ + ) + + fun testFunBody7() = doFileTest( + """ + trait T + fun other() where U: T + """, + """ + trait T + fun other() where U : T { + + } + """ + ) + + fun testFunBody8() = doFileTest( + """ + fun Int.other + """, + """ + fun Int.other() { + + } + """ + ) + + fun testInLambda1() = doFunTest( + """ + some { + p -> + } + """, + """ + some { + p -> + + } + """ + ) + + fun testInLambda2() = doFunTest( + """ + some { + p -> + } + """, + """ + some { + p -> + + } + """ + ) + + fun testInLambda3() = doFunTest( + """ + some { + (p: Int) : Int -> + } + """, + """ + some { + (p: Int) : Int -> + + } + """ + ) + + fun testInLambda4() = doFunTest( + """ + some { + (p: Int) : Int -> + } + """, + """ + some { + (p: Int) : Int -> + + } + """ + ) + + fun doFunTest(before: String, after: String) { + fun String.withFunContext(): String { + val bodyText = "//----${this.trimIndent()}//----" + val withIndent = bodyText.split("\n").map { " $it" }.joinToString(separator = "\n") + + return "fun method() {\n${withIndent}\n}" + } + + doTest(before.withFunContext(), after.withFunContext()) + } + + fun doFileTest(before: String, after: String) { + doTest(before.trimIndent().removeFirstEmptyLines(), after.trimIndent().removeFirstEmptyLines()) + } + + fun doTest(before: String, after: String) { + myFixture.configureByText(JetFileType.INSTANCE, before) + myFixture.performEditorAction(IdeActions.ACTION_EDITOR_COMPLETE_STATEMENT) + myFixture.checkResult(after) + } + + override fun getProjectDescriptor(): LightProjectDescriptor = LightCodeInsightFixtureTestCase.JAVA_LATEST + + private fun String.removeFirstEmptyLines() = this.split("\n").dropWhile { it.isEmpty() }.joinToString(separator = "\n") +} diff --git a/idea/tests/org/jetbrains/jet/plugin/conversion/copy/AbstractJavaToKotlinCopyPasteConversionTest.java b/idea/tests/org/jetbrains/jet/plugin/conversion/copy/AbstractJavaToKotlinCopyPasteConversionTest.java index 5996ffba61a..7a2eff686db 100644 --- a/idea/tests/org/jetbrains/jet/plugin/conversion/copy/AbstractJavaToKotlinCopyPasteConversionTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/conversion/copy/AbstractJavaToKotlinCopyPasteConversionTest.java @@ -17,7 +17,10 @@ package org.jetbrains.jet.plugin.conversion.copy; import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.testFramework.LightProjectDescriptor; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.plugin.JetWithJdkAndRuntimeLightProjectDescriptor; import org.jetbrains.jet.plugin.PluginTestCaseBase; import org.jetbrains.jet.plugin.editor.JetEditorOptions; @@ -26,6 +29,12 @@ public abstract class AbstractJavaToKotlinCopyPasteConversionTest extends LightC private static final String BASE_PATH = PluginTestCaseBase.getTestDataPathBase() + "/copyPaste/conversion"; private JetEditorOptions oldState = null; + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JetWithJdkAndRuntimeLightProjectDescriptor.INSTANCE; + } + @Override protected void setUp() throws Exception { super.setUp(); diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt index ab25a5b2e2c..d05f7197025 100644 --- a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt @@ -35,14 +35,43 @@ import com.sun.jdi.ObjectReference import org.jetbrains.jet.lang.psi.JetCodeFragment import java.util.Collections import com.intellij.debugger.engine.evaluation.EvaluateException +import com.intellij.execution.process.ProcessOutputTypes +import org.apache.log4j.AppenderSkeleton +import org.apache.log4j.spi.LoggingEvent +import org.apache.log4j.Level +import org.apache.log4j.Logger public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestCase() { - fun doTest(path: String) { + private val logger = Logger.getLogger(javaClass())!! + + private val appender = object : AppenderSkeleton() { + override fun append(event: LoggingEvent?) { + println(event?.getRenderedMessage(), ProcessOutputTypes.SYSTEM) + } + override fun close() {} + override fun requiresLayout() = false + } + + private var oldLogLevel: Level? = null + + override fun setUp() { + super.setUp() + + oldLogLevel = logger.getLevel() + logger.setLevel(Level.DEBUG) + logger.addAppender(appender) + } + + override fun tearDown() { + logger.setLevel(oldLogLevel) + logger.removeAppender(appender) + + super.tearDown() + } + + fun doSingleBreakpointTest(path: String) { val file = File(path) - val fileContent = FileUtil.loadFile(file, true) - val expressions = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileContent, "// EXPRESSION: ") - val expectedExpressionResults = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileContent, "// RESULT: ") - assert(expressions.size == expectedExpressionResults.size, "Sizes of test directives are different") + val expressions = loadTestDirectivesPairs(file, "// EXPRESSION: ", "// RESULT: ") val blocks = findFilesWithBlocks(file).map { FileUtil.loadFile(it, true) } val expectedBlockResults = blocks.map { InTextDirectivesUtils.findLinesWithPrefixesRemoved(it, "// RESULT: ").makeString("\n") } @@ -51,34 +80,70 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestC onBreakpoint { val exceptions = linkedMapOf() - for ((i, expression) in expressions.withIndices()) { - try { - evaluate(expression, CodeFragmentKind.EXPRESSION, expectedExpressionResults[i]) - } - catch (e: Throwable) { - exceptions.put(expression, e) + for ((expression, expected) in expressions) { + mayThrow(exceptions, expression) { + evaluate(expression, CodeFragmentKind.EXPRESSION, expected) } } for ((i, block) in blocks.withIndices()) { - try { + mayThrow(exceptions, block) { evaluate(block, CodeFragmentKind.CODE_BLOCK, expectedBlockResults[i]) } - catch (e: Throwable) { - exceptions.put(block, e) - } } - if (!exceptions.empty) { - for (exc in exceptions.values()) { - exc.printStackTrace() - } - throw AssertionError("Test failed:\n" + exceptions.map { "expression: ${it.key}, exception: ${it.value.getMessage()}" }.makeString("\n")) - } + checkExceptions(exceptions) } finish() } + fun doMultipleBreakpointsTest(path: String) { + val expressions = loadTestDirectivesPairs(File(path), "// EXPRESSION: ", "// RESULT: ") + + createDebugProcess(path) + + val exceptions = linkedMapOf() + for ((expression, expected) in expressions) { + mayThrow(exceptions, expression) { + onBreakpoint { + evaluate(expression, CodeFragmentKind.EXPRESSION, expected) + } + } + } + + checkExceptions(exceptions) + + finish() + } + + + + private fun checkExceptions(exceptions: MutableMap) { + if (!exceptions.empty) { + for (exc in exceptions.values()) { + exc.printStackTrace() + } + throw AssertionError("Test failed:\n" + exceptions.map { "expression: ${it.key}, exception: ${it.value.getMessage()}" }.makeString("\n")) + } + } + + private fun mayThrow(map: MutableMap, expression: String, f: () -> Unit) { + try { + f() + } + catch (e: Throwable) { + map.put(expression, e) + } + } + + private fun loadTestDirectivesPairs(file: File, directivePrefix: String, expectedPrefix: String): List> { + val fileContent = FileUtil.loadFile(file, true) + val directives = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileContent, directivePrefix) + val expected = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileContent, expectedPrefix) + assert(directives.size == expected.size, "Sizes of test directives are different") + return directives.zip(expected) + } + private fun findFilesWithBlocks(mainFile: File): List { val mainFileName = mainFile.getName() return mainFile.getParentFile()?.listFiles()?.filter { it.name.startsWith(mainFileName) && it.name != mainFileName } ?: Collections.emptyList() @@ -106,10 +171,10 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestC val evaluator = DebuggerInvocationUtil.commitAndRunReadAction(getProject()) { EvaluatorBuilderImpl.build(TextWithImportsImpl( - codeFragmentKind, - text, - JetCodeFragment.getImportsForElement(contextElement), - JetFileType.INSTANCE), + codeFragmentKind, + text, + JetCodeFragment.getImportsForElement(contextElement), + JetFileType.INSTANCE), contextElement, sourcePosition) } @@ -120,7 +185,7 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestC Assert.assertTrue("Evaluate expression returns wrong result for $text:\nexpected = $expectedResult\nactual = $actualResult\n", expectedResult == actualResult) } catch (e: EvaluateException) { - Assert.assertTrue("Evaluate expression throws wrong exception for $text:\nexpected = $expectedResult\nactual = ${e.getMessage()}\n", expectedResult == e.getMessage()) + Assert.assertTrue("Evaluate expression throws wrong exception for $text:\nexpected = $expectedResult\nactual = ${e.getMessage()}\n", expectedResult == e.getMessage()?.replaceFirst("id=[0-9]*", "id=ID")) } finally { resume(this) diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java index 73973e98407..538ea354fb7 100644 --- a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -30,105 +30,138 @@ import org.jetbrains.jet.plugin.debugger.evaluate.AbstractKotlinEvaluateExpressi /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") -@TestMetadata("idea/testData/debugger/tinyApp/src/evaluate") +@InnerTestClasses({KotlinEvaluateExpressionTestGenerated.SingleBreakpoint.class, KotlinEvaluateExpressionTestGenerated.MultipleBreakpoints.class}) public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluateExpressionTest { - @TestMetadata("abstractFunCall.kt") - public void testAbstractFunCall() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/abstractFunCall.kt"); + @TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint") + public static class SingleBreakpoint extends AbstractKotlinEvaluateExpressionTest { + @TestMetadata("abstractFunCall.kt") + public void testAbstractFunCall() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/abstractFunCall.kt"); + } + + public void testAllFilesPresentInSingleBreakpoint() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("arrays.kt") + public void testArrays() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/arrays.kt"); + } + + @TestMetadata("classFromAnotherPackage.kt") + public void testClassFromAnotherPackage() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/classFromAnotherPackage.kt"); + } + + @TestMetadata("classObjectVal.kt") + public void testClassObjectVal() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/classObjectVal.kt"); + } + + @TestMetadata("collections.kt") + public void testCollections() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/collections.kt"); + } + + @TestMetadata("dependentOnFile.kt") + public void testDependentOnFile() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/dependentOnFile.kt"); + } + + @TestMetadata("doubles.kt") + public void testDoubles() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/doubles.kt"); + } + + @TestMetadata("enums.kt") + public void testEnums() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/enums.kt"); + } + + @TestMetadata("errors.kt") + public void testErrors() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/errors.kt"); + } + + @TestMetadata("extractLocalVariables.kt") + public void testExtractLocalVariables() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractLocalVariables.kt"); + } + + @TestMetadata("extractThis.kt") + public void testExtractThis() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractThis.kt"); + } + + @TestMetadata("extractVariablesFromCall.kt") + public void testExtractVariablesFromCall() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/extractVariablesFromCall.kt"); + } + + @TestMetadata("imports.kt") + public void testImports() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/imports.kt"); + } + + @TestMetadata("insertInBlock.kt") + public void testInsertInBlock() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/insertInBlock.kt"); + } + + @TestMetadata("multilineExpressionAtBreakpoint.kt") + public void testMultilineExpressionAtBreakpoint() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/multilineExpressionAtBreakpoint.kt"); + } + + @TestMetadata("privateMember.kt") + public void testPrivateMember() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/privateMember.kt"); + } + + @TestMetadata("protectedMember.kt") + public void testProtectedMember() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/protectedMember.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/simple.kt"); + } + + @TestMetadata("stdlib.kt") + public void testStdlib() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/stdlib.kt"); + } + + @TestMetadata("vars.kt") + public void testVars() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/vars.kt"); + } + } - public void testAllFilesPresentInEvaluate() throws Exception { - JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/debugger/tinyApp/src/evaluate"), Pattern.compile("^(.+)\\.kt$"), true); + @TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints") + public static class MultipleBreakpoints extends AbstractKotlinEvaluateExpressionTest { + public void testAllFilesPresentInMultipleBreakpoints() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("clearCache.kt") + public void testClearCache() throws Exception { + doMultipleBreakpointsTest("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/clearCache.kt"); + } + + @TestMetadata("exceptions.kt") + public void testExceptions() throws Exception { + doMultipleBreakpointsTest("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/exceptions.kt"); + } + } - @TestMetadata("arrays.kt") - public void testArrays() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/arrays.kt"); + public static Test suite() { + TestSuite suite = new TestSuite("KotlinEvaluateExpressionTestGenerated"); + suite.addTestSuite(SingleBreakpoint.class); + suite.addTestSuite(MultipleBreakpoints.class); + return suite; } - - @TestMetadata("classFromAnotherPackage.kt") - public void testClassFromAnotherPackage() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/classFromAnotherPackage.kt"); - } - - @TestMetadata("classObjectVal.kt") - public void testClassObjectVal() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/classObjectVal.kt"); - } - - @TestMetadata("collections.kt") - public void testCollections() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/collections.kt"); - } - - @TestMetadata("dependentOnFile.kt") - public void testDependentOnFile() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/dependentOnFile.kt"); - } - - @TestMetadata("enums.kt") - public void testEnums() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/enums.kt"); - } - - @TestMetadata("errors.kt") - public void testErrors() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/errors.kt"); - } - - @TestMetadata("extractLocalVariables.kt") - public void testExtractLocalVariables() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/extractLocalVariables.kt"); - } - - @TestMetadata("extractThis.kt") - public void testExtractThis() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/extractThis.kt"); - } - - @TestMetadata("extractVariablesFromCall.kt") - public void testExtractVariablesFromCall() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/extractVariablesFromCall.kt"); - } - - @TestMetadata("imports.kt") - public void testImports() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/imports.kt"); - } - - @TestMetadata("insertInBlock.kt") - public void testInsertInBlock() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/insertInBlock.kt"); - } - - @TestMetadata("multilineExpressionAtBreakpoint.kt") - public void testMultilineExpressionAtBreakpoint() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/multilineExpressionAtBreakpoint.kt"); - } - - @TestMetadata("privateMember.kt") - public void testPrivateMember() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/privateMember.kt"); - } - - @TestMetadata("protectedMember.kt") - public void testProtectedMember() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/protectedMember.kt"); - } - - @TestMetadata("simple.kt") - public void testSimple() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/simple.kt"); - } - - @TestMetadata("stdlib.kt") - public void testStdlib() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/stdlib.kt"); - } - - @TestMetadata("vars.kt") - public void testVars() throws Exception { - doTest("idea/testData/debugger/tinyApp/src/evaluate/vars.kt"); - } - } diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java index 7f93f8f37ed..63155eca981 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java @@ -2263,6 +2263,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangePrimaryConstructorParameterType.kt"); } + @TestMetadata("beforeMultiFakeOverride.kt") + public void testMultiFakeOverride() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeMultiFakeOverride.kt"); + } + } @TestMetadata("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression") @@ -2306,6 +2311,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeExpectedTypeMismatch.kt"); } + @TestMetadata("beforeMultiFakeOverride.kt") + public void testMultiFakeOverride() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverride.kt"); + } + + @TestMetadata("beforeMultiFakeOverrideForOperatorConvention.kt") + public void testMultiFakeOverrideForOperatorConvention() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverrideForOperatorConvention.kt"); + } + @TestMetadata("beforePropertyGetterInitializerTypeMismatch.kt") public void testPropertyGetterInitializerTypeMismatch() throws Exception { doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforePropertyGetterInitializerTypeMismatch.kt"); diff --git a/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/AbstractJetExtractionTest.kt b/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/AbstractJetExtractionTest.kt index 906082094e3..456534a3ee5 100644 --- a/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/AbstractJetExtractionTest.kt +++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/AbstractJetExtractionTest.kt @@ -31,6 +31,11 @@ import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.PsiWhiteSpace import org.jetbrains.jet.lang.psi.JetPackageDirective +import org.jetbrains.jet.InTextDirectivesUtils +import org.jetbrains.jet.renderer.DescriptorRenderer +import java.util.ArrayList +import com.intellij.util.containers.ContainerUtil +import kotlin.test.assertEquals import org.jetbrains.jet.plugin.JetLightCodeInsightFixtureTestCase import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase @@ -68,9 +73,24 @@ public abstract class AbstractJetExtractionTest() : JetLightCodeInsightFixtureTe } ) + val expectedParameterTypes = ArrayList() + val fileText = file.getText() + val expectedTypes = + InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, "// PARAM_TYPES: ") + .mapTo(expectedParameterTypes) { "[$it]" } + .joinToString() + + val renderer = DescriptorRenderer.DEBUG_TEXT + val editor = fixture.getEditor() selectElements(editor, file) { (elements, previousSibling) -> - ExtractKotlinFunctionHandler().doInvoke(editor, file, elements, explicitPreviousSibling ?: previousSibling) + ExtractKotlinFunctionHandler().doInvoke(editor, file, elements, explicitPreviousSibling ?: previousSibling) { + val actualTypes = (ContainerUtil.createMaybeSingletonList(it.receiverParameter) + it.parameters).map { + it.parameterTypeCandidates.map { renderer.renderType(it) }. joinToString(", ", "[", "]") + }.joinToString() + + assertEquals(expectedTypes, actualTypes, "Expected types mismatch.") + } } } } @@ -91,7 +111,7 @@ public abstract class AbstractJetExtractionTest() : JetLightCodeInsightFixtureTe JetTestUtils.assertEqualsToFile(afterFile, file.getText()!!) } catch(e: Exception) { - val message = if (e is ConflictsInTestsException) e.getMessages().sort().makeString(" ") else e.getMessage() + val message = if (e is ConflictsInTestsException) e.getMessages().sort().joinToString(" ") else e.getMessage() JetTestUtils.assertEqualsToFile(conflictFile, message?.replace("\n", " ") ?: e.javaClass.getName()) } } diff --git a/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java index a867122af38..1769329e2d3 100644 --- a/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/JetExtractionTestGenerated.java @@ -447,6 +447,21 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/simpleEvalExpr.kt"); } + @TestMetadata("trailingLambdaEmptyArgList.kt") + public void testTrailingLambdaEmptyArgList() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaEmptyArgList.kt"); + } + + @TestMetadata("trailingLambdaNoArgList.kt") + public void testTrailingLambdaNoArgList() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNoArgList.kt"); + } + + @TestMetadata("trailingLambdaNonEmptyArgList.kt") + public void testTrailingLambdaNonEmptyArgList() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/trailingLambdaNonEmptyArgList.kt"); + } + } @TestMetadata("idea/testData/refactoring/extractFunction/controlFlow/outputValues") @@ -576,6 +591,21 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/outputValueWithReturn.kt"); } + @TestMetadata("valueUsedInAnonymousObject.kt") + public void testValueUsedInAnonymousObject() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInAnonymousObject.kt"); + } + + @TestMetadata("valueUsedInLambda.kt") + public void testValueUsedInLambda() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLambda.kt"); + } + + @TestMetadata("valueUsedInLocalFunction.kt") + public void testValueUsedInLocalFunction() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/valueUsedInLocalFunction.kt"); + } + @TestMetadata("variablesOutOfScope.kt") public void testVariablesOutOfScope() throws Exception { doExtractFunctionTest("idea/testData/refactoring/extractFunction/controlFlow/unextractable/variablesOutOfScope.kt"); @@ -636,12 +666,50 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { } @TestMetadata("idea/testData/refactoring/extractFunction/parameters") - @InnerTestClasses({Parameters.ExtractSuper.class, Parameters.ExtractThis.class, Parameters.Misc.class, Parameters.NonDenotableTypes.class}) + @InnerTestClasses({Parameters.CandidateTypes.class, Parameters.ExtractSuper.class, Parameters.ExtractThis.class, Parameters.It.class, Parameters.Misc.class, Parameters.NonDenotableTypes.class}) public static class Parameters extends AbstractJetExtractionTest { public void testAllFilesPresentInParameters() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/refactoring/extractFunction/parameters"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("idea/testData/refactoring/extractFunction/parameters/candidateTypes") + public static class CandidateTypes extends AbstractJetExtractionTest { + public void testAllFilesPresentInCandidateTypes() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/refactoring/extractFunction/parameters/candidateTypes"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("nonNullableTypes.kt") + public void testNonNullableTypes() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt"); + } + + @TestMetadata("nullableTypes.kt") + public void testNullableTypes() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/parameters/candidateTypes/nullableTypes.kt"); + } + + @TestMetadata("typeHierarchy1.kt") + public void testTypeHierarchy1() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy1.kt"); + } + + @TestMetadata("typeHierarchy2.kt") + public void testTypeHierarchy2() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy2.kt"); + } + + @TestMetadata("typeHierarchy3.kt") + public void testTypeHierarchy3() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy3.kt"); + } + + @TestMetadata("typeHierarchy4.kt") + public void testTypeHierarchy4() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy4.kt"); + } + + } + @TestMetadata("idea/testData/refactoring/extractFunction/parameters/extractSuper") public static class ExtractSuper extends AbstractJetExtractionTest { public void testAllFilesPresentInExtractSuper() throws Exception { @@ -713,6 +781,34 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { } + @TestMetadata("idea/testData/refactoring/extractFunction/parameters/it") + public static class It extends AbstractJetExtractionTest { + public void testAllFilesPresentInIt() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/refactoring/extractFunction/parameters/it"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("innerIt.kt") + public void testInnerIt() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/parameters/it/innerIt.kt"); + } + + @TestMetadata("lambdaWithIt.kt") + public void testLambdaWithIt() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/parameters/it/lambdaWithIt.kt"); + } + + @TestMetadata("outerIt.kt") + public void testOuterIt() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/parameters/it/outerIt.kt"); + } + + @TestMetadata("simpleIt.kt") + public void testSimpleIt() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/parameters/it/simpleIt.kt"); + } + + } + @TestMetadata("idea/testData/refactoring/extractFunction/parameters/misc") public static class Misc extends AbstractJetExtractionTest { public void testAllFilesPresentInMisc() throws Exception { @@ -794,6 +890,11 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doExtractFunctionTest("idea/testData/refactoring/extractFunction/parameters/misc/usagesInCallArgs.kt"); } + @TestMetadata("variableAsFunction.kt") + public void testVariableAsFunction() throws Exception { + doExtractFunctionTest("idea/testData/refactoring/extractFunction/parameters/misc/variableAsFunction.kt"); + } + } @TestMetadata("idea/testData/refactoring/extractFunction/parameters/nonDenotableTypes") @@ -817,8 +918,10 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { public static Test innerSuite() { TestSuite suite = new TestSuite("Parameters"); suite.addTestSuite(Parameters.class); + suite.addTestSuite(CandidateTypes.class); suite.addTestSuite(ExtractSuper.class); suite.addTestSuite(ExtractThis.class); + suite.addTestSuite(It.class); suite.addTestSuite(Misc.class); suite.addTestSuite(NonDenotableTypes.class); return suite; diff --git a/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java index 83ae5f63739..8febd6a824d 100644 --- a/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java @@ -1061,6 +1061,11 @@ public class LazyResolveByStubTestGenerated extends AbstractLazyResolveByStubTes doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/prop/CollectionSize.kt"); } + @TestMetadata("Constants.kt") + public void testConstants() throws Exception { + doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/prop/Constants.kt"); + } + @TestMetadata("ExtValClass.kt") public void testExtValClass() throws Exception { doTestCheckingPrimaryConstructorsAndAccessors("compiler/testData/loadJava/compiledKotlin/prop/ExtValClass.kt"); diff --git a/idea/tests/org/jetbrains/jet/shortenRefs/AbstractShortenRefsTest.kt b/idea/tests/org/jetbrains/jet/shortenRefs/AbstractShortenRefsTest.kt index fa96de9b0d4..a99e6b8be13 100644 --- a/idea/tests/org/jetbrains/jet/shortenRefs/AbstractShortenRefsTest.kt +++ b/idea/tests/org/jetbrains/jet/shortenRefs/AbstractShortenRefsTest.kt @@ -16,6 +16,7 @@ package org.jetbrains.jet.shortenRefs +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import org.jetbrains.jet.lang.psi.JetFile import org.jetbrains.jet.plugin.JetWithJdkAndRuntimeLightProjectDescriptor import com.intellij.openapi.application.ApplicationManager @@ -24,35 +25,48 @@ import com.intellij.openapi.command.CommandProcessor import org.jetbrains.jet.plugin.codeInsight.ShortenReferences import org.jetbrains.jet.JetTestCaseBuilder import org.jetbrains.jet.plugin.JetLightCodeInsightFixtureTestCase +import com.intellij.codeInsight.CodeInsightSettings +import org.jetbrains.jet.InTextDirectivesUtils abstract class AbstractShortenRefsTest : JetLightCodeInsightFixtureTestCase() { override fun getTestDataPath() = JetTestCaseBuilder.getHomeDirectory() override fun getProjectDescriptor() = JetWithJdkAndRuntimeLightProjectDescriptor.INSTANCE protected fun doTest(testPath: String) { - val fixture = myFixture - val dependencyPath = testPath.replace(".kt", ".dependency.kt") - if (File(dependencyPath).exists()) { - fixture.configureByFile(dependencyPath) - } - val javaDependencyPath = testPath.replace(".kt", ".dependency.java") - if (File(javaDependencyPath).exists()) { - fixture.configureByFile(javaDependencyPath) - } + val codeInsightSettings = CodeInsightSettings.getInstance() + val optimizeImportsBefore = codeInsightSettings.OPTIMIZE_IMPORTS_ON_THE_FLY - fixture.configureByFile(testPath) - - val file = fixture.getFile() as JetFile - val selectionModel = fixture.getEditor().getSelectionModel() - if (!selectionModel.hasSelection()) error("No selection in input file") - - CommandProcessor.getInstance().executeCommand(getProject(), { - ApplicationManager.getApplication()!!.runWriteAction { - ShortenReferences.process(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()) + try { + val fixture = myFixture + val dependencyPath = testPath.replace(".kt", ".dependency.kt") + if (File(dependencyPath).exists()) { + fixture.configureByFile(dependencyPath) + } + val javaDependencyPath = testPath.replace(".kt", ".dependency.java") + if (File(javaDependencyPath).exists()) { + fixture.configureByFile(javaDependencyPath) } - }, null, null) - selectionModel.removeSelection() - fixture.checkResultByFile(testPath + ".after") + fixture.configureByFile(testPath) + + val file = fixture.getFile() as JetFile + val selectionModel = fixture.getEditor().getSelectionModel() + if (!selectionModel.hasSelection()) error("No selection in input file") + + codeInsightSettings.OPTIMIZE_IMPORTS_ON_THE_FLY = + InTextDirectivesUtils.isDirectiveDefined(file.getText(), "// OPTIMIZE_IMPORTS") + + CommandProcessor.getInstance().executeCommand(getProject(), { + ApplicationManager.getApplication()!!.runWriteAction { + ShortenReferences.process(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()) + } + }, null, null) + selectionModel.removeSelection() + + fixture.checkResultByFile(testPath + ".after") + } + finally { + codeInsightSettings.OPTIMIZE_IMPORTS_ON_THE_FLY = optimizeImportsBefore + } } } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/shortenRefs/ShortenRefsTestGenerated.java b/idea/tests/org/jetbrains/jet/shortenRefs/ShortenRefsTestGenerated.java index 27fad679ecc..03e71a462e5 100644 --- a/idea/tests/org/jetbrains/jet/shortenRefs/ShortenRefsTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/shortenRefs/ShortenRefsTestGenerated.java @@ -31,7 +31,7 @@ import org.jetbrains.jet.shortenRefs.AbstractShortenRefsTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("idea/testData/shortenRefs") -@InnerTestClasses({ShortenRefsTestGenerated.Constructor.class, ShortenRefsTestGenerated.Java.class, ShortenRefsTestGenerated.Type.class}) +@InnerTestClasses({ShortenRefsTestGenerated.Constructor.class, ShortenRefsTestGenerated.Imports.class, ShortenRefsTestGenerated.Java.class, ShortenRefsTestGenerated.Type.class}) public class ShortenRefsTestGenerated extends AbstractShortenRefsTest { public void testAllFilesPresentInShortenRefs() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/shortenRefs"), Pattern.compile("^([^\\.]+)\\.kt$"), true); @@ -47,6 +47,11 @@ public class ShortenRefsTestGenerated extends AbstractShortenRefsTest { doTest("idea/testData/shortenRefs/JavaStaticMethod.kt"); } + @TestMetadata("noShortening.kt") + public void testNoShortening() throws Exception { + doTest("idea/testData/shortenRefs/noShortening.kt"); + } + @TestMetadata("idea/testData/shortenRefs/constructor") public static class Constructor extends AbstractShortenRefsTest { public void testAllFilesPresentInConstructor() throws Exception { @@ -125,6 +130,29 @@ public class ShortenRefsTestGenerated extends AbstractShortenRefsTest { } + @TestMetadata("idea/testData/shortenRefs/imports") + public static class Imports extends AbstractShortenRefsTest { + public void testAllFilesPresentInImports() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/shortenRefs/imports"), Pattern.compile("^([^\\.]+)\\.kt$"), true); + } + + @TestMetadata("leaveQualifiedConstructor.kt") + public void testLeaveQualifiedConstructor() throws Exception { + doTest("idea/testData/shortenRefs/imports/leaveQualifiedConstructor.kt"); + } + + @TestMetadata("leaveQualifiedType.kt") + public void testLeaveQualifiedType() throws Exception { + doTest("idea/testData/shortenRefs/imports/leaveQualifiedType.kt"); + } + + @TestMetadata("optimizeMultipleImports.kt") + public void testOptimizeMultipleImports() throws Exception { + doTest("idea/testData/shortenRefs/imports/optimizeMultipleImports.kt"); + } + + } + @TestMetadata("idea/testData/shortenRefs/java") public static class Java extends AbstractShortenRefsTest { public void testAllFilesPresentInJava() throws Exception { @@ -270,6 +298,7 @@ public class ShortenRefsTestGenerated extends AbstractShortenRefsTest { TestSuite suite = new TestSuite("ShortenRefsTestGenerated"); suite.addTestSuite(ShortenRefsTestGenerated.class); suite.addTestSuite(Constructor.class); + suite.addTestSuite(Imports.class); suite.addTestSuite(Java.class); suite.addTestSuite(Type.class); return suite; diff --git a/j2k/src/org/jetbrains/jet/j2k/CodeBuilder.kt b/j2k/src/org/jetbrains/jet/j2k/CodeBuilder.kt new file mode 100644 index 00000000000..3927e0725ab --- /dev/null +++ b/j2k/src/org/jetbrains/jet/j2k/CodeBuilder.kt @@ -0,0 +1,234 @@ +/* + * 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.j2k + +import com.intellij.psi.* +import java.util.HashSet +import org.jetbrains.jet.lang.psi.psiUtil.isAncestor +import java.util.ArrayList +import org.jetbrains.jet.j2k.ast.Element +import org.jetbrains.jet.j2k.ast.Modifiers +import kotlin.platform.platformName + +fun CodeBuilder.append(generators: Collection<() -> T>, separator: String, prefix: String = "", suffix: String = ""): CodeBuilder { + if (generators.isNotEmpty()) { + append(prefix) + var first = true + for (generator in generators) { + if (!first) { + append(separator) + } + generator() + first = false + } + append(suffix) + } + return this +} + +platformName("appendElements") +fun CodeBuilder.append(elements: Collection, separator: String, prefix: String = "", suffix: String = ""): CodeBuilder { + return append(elements.filter { !it.isEmpty }.map { { append(it) } }, separator, prefix, suffix) +} + +class CodeBuilder(private val topElement: PsiElement?) { + private val builder = StringBuilder() + private var endOfLineCommentAtEnd = false + + private val commentsAndSpacesUsed = HashSet() + + public fun append(text: String, endOfLineComment: Boolean = false): CodeBuilder { + if (text.isEmpty()) { + assert(!endOfLineComment) + return this + } + + if (endOfLineCommentAtEnd) { + if (text[0] != '\n' && text[0] != '\r') builder.append('\n') + endOfLineCommentAtEnd = false + } + + builder.append(text) + endOfLineCommentAtEnd = endOfLineComment + return this + } + + public val result: String + get() = builder.toString() + + public fun append(element: Element): CodeBuilder { + if (element.isEmpty) return this // do not insert comment and spaces for empty elements to avoid multiple blank lines + + if (element.prototypes.isEmpty() || topElement == null) { + element.generateCode(this) + return this + } + + val prefixElements = ArrayList(2) + val postfixElements = ArrayList(2) + for ((prototype, inheritBlankLinesBefore) in element.prototypes) { + assert(prototype !is PsiComment) + assert(prototype !is PsiWhiteSpace) + assert(topElement.isAncestor(prototype)) + prefixElements.collectPrefixElements(prototype, inheritBlankLinesBefore) + postfixElements.collectPostfixElements(prototype) + } + + commentsAndSpacesUsed.addAll(prefixElements) + commentsAndSpacesUsed.addAll(postfixElements) + + for (i in prefixElements.indices) { + val e = prefixElements[i] + if (i == 0 && e is PsiWhiteSpace) { + if (e.newLinesCount() > 1) { // insert at maximum one blank line + append("\n") + } + } + else { + append(e.getText()!!, e.isEndOfLineComment()) + } + } + + element.generateCode(this) + + // scan for all comments inside which are not yet used in the text and put them here to not loose any comment from code + for ((prototype, _) in element.prototypes) { + prototype.accept(object : JavaRecursiveElementVisitor(){ + override fun visitComment(comment: PsiComment) { + if (commentsAndSpacesUsed.add(comment)) { + append(comment.getText()!!, comment.isEndOfLineComment()) + } + } + }) + } + + postfixElements.forEach { append(it.getText()!!, it.isEndOfLineComment()) } + + return this + } + + private fun MutableList.collectPrefixElements(element: PsiElement, allowBlankLinesBefore: Boolean) { + val atStart = ArrayList(2).collectCommentsAndSpacesAtStart(element) + + val before = ArrayList(2).collectCommentsAndSpacesBefore(element) + if (!allowBlankLinesBefore && before.lastOrNull() is PsiWhiteSpace) { + before.remove(before.size - 1) + } + + addAll(before.reverse()) + addAll(atStart) + } + + private fun MutableList.collectPostfixElements(element: PsiElement) { + val atEnd = ArrayList(2).collectCommentsAndSpacesAtEnd(element) + + val after = ArrayList(2).collectCommentsAndSpacesAfter(element) + if (after.isNotEmpty()) { + val last = after.last() + if (last is PsiWhiteSpace) { + after.remove(after.size - 1) + } + } + + addAll(atEnd.reverse()) + addAll(after) + } + + private fun MutableList.collectCommentsAndSpacesBefore(element: PsiElement): MutableList { + if (element == topElement) return this + + val prev = element.getPrevSibling() + if (prev != null) { + if (prev.isCommentOrSpace()) { + if (prev !in commentsAndSpacesUsed) { + add(prev) + collectCommentsAndSpacesBefore(prev) + } + } + else if (prev.isEmptyElement()){ + collectCommentsAndSpacesBefore(prev) + } + } + else { + collectCommentsAndSpacesBefore(element.getParent()!!) + } + return this + } + + private fun MutableList.collectCommentsAndSpacesAfter(element: PsiElement): MutableList { + if (element == topElement) return this + + val next = element.getNextSibling() + if (next != null) { + if (next.isCommentOrSpace()) { + if (next is PsiWhiteSpace && next.hasNewLines()) return this // do not attach anything on next line after element + if (next !in commentsAndSpacesUsed) { + add(next) + collectCommentsAndSpacesAfter(next) + } + } + else if (next.isEmptyElement()){ + collectCommentsAndSpacesAfter(next) + } + } + else { + collectCommentsAndSpacesAfter(element.getParent()!!) + } + return this + } + + private fun MutableList.collectCommentsAndSpacesAtStart(element: PsiElement): MutableList { + var child = element.getFirstChild() + while(child != null) { + if (child!!.isCommentOrSpace()) { + if (child !in commentsAndSpacesUsed) add(child!!) else break + } + else if (!child!!.isEmptyElement()) { + collectCommentsAndSpacesAtStart(child!!) + break + } + child = child!!.getNextSibling() + } + return this + } + + private fun MutableList.collectCommentsAndSpacesAtEnd(element: PsiElement): MutableList { + var child = element.getLastChild() + while(child != null) { + if (child!!.isCommentOrSpace()) { + if (child !in commentsAndSpacesUsed) add(child!!) else break + } + else if (!child!!.isEmptyElement()) { + collectCommentsAndSpacesAtEnd(child!!) + break + } + child = child!!.getPrevSibling() + } + return this + } + + private fun PsiElement.isCommentOrSpace() = this is PsiComment || this is PsiWhiteSpace + + private fun PsiElement.isEndOfLineComment() = this is PsiComment && getTokenType() == JavaTokenType.END_OF_LINE_COMMENT + + private fun PsiElement.isEmptyElement() = getFirstChild() == null && getTextLength() == 0 + + private fun PsiWhiteSpace.newLinesCount() = getText()!!.count { it == '\n' } //TODO: this is not correct!! + + private fun PsiWhiteSpace.hasNewLines() = getText()!!.any { it == '\n' || it == '\r' } +} + diff --git a/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt b/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt index cc9330dfc5d..1a5608ce4e5 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt @@ -80,8 +80,7 @@ fun PsiElement.getContainingConstructor(): PsiMethod? { fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean { val ref = getMethodExpression() if (ref.getCanonicalText() == "super") { - val target = ref.resolve() - return target is PsiMethod && target.isConstructor() + return ref.resolve()?.isConstructor() ?: false } return false } @@ -89,3 +88,4 @@ fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean { fun PsiReferenceExpression.isThisConstructorCall(): Boolean = getReferences().filter { it.getCanonicalText() == "this" }.map { it.resolve() }.any { it is PsiMethod && it.isConstructor() } +fun PsiElement.isConstructor(): Boolean = this is PsiMethod && this.isConstructor() diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.kt b/j2k/src/org/jetbrains/jet/j2k/Converter.kt index 96a94230038..b33d95ba986 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Converter.kt @@ -25,106 +25,164 @@ import org.jetbrains.jet.lang.types.expressions.OperatorConventions.* import com.intellij.openapi.project.Project import com.intellij.psi.util.PsiUtil -public class Converter(val project: Project, val settings: ConverterSettings) { +public trait ConversionScope { + public fun contains(element: PsiElement): Boolean +} - private val typeConverter = TypeConverter(settings) +public class FilesConversionScope(val files: Collection) : ConversionScope { + override fun contains(element: PsiElement) = files.any { element.getContainingFile() == it } +} - private var classIdentifiersSet: MutableSet = HashSet() +public class Converter private(val project: Project, val settings: ConverterSettings, val conversionScope: ConversionScope, val state: Converter.State) { + private class State(val typeConverter: TypeConverter, + val methodReturnType: PsiType?, + val expressionVisitorFactory: (Converter) -> ExpressionVisitor, + val statementVisitorFactory: (Converter) -> StatementVisitor) - private val dispatcher: Dispatcher = Dispatcher(this, typeConverter) + val typeConverter: TypeConverter get() = state.typeConverter + val methodReturnType: PsiType? get() = state.methodReturnType - public var methodReturnType: PsiType? = null - private set + private val expressionVisitor = state.expressionVisitorFactory(this) + private val statementVisitor = state.statementVisitorFactory(this) - public fun setClassIdentifiers(identifiers: MutableSet) { - classIdentifiersSet = identifiers + class object { + public fun create(project: Project, settings: ConverterSettings, conversionScope: ConversionScope): Converter + = Converter(project, settings, conversionScope, State(TypeConverter(settings, conversionScope), null, { ExpressionVisitor(it) }, { StatementVisitor(it) })) } - public fun getClassIdentifiers(): Set { - return Collections.unmodifiableSet(classIdentifiersSet) + fun withMethodReturnType(methodReturnType: PsiType?): Converter + = Converter(project, settings, conversionScope, State(typeConverter, methodReturnType, state.expressionVisitorFactory, state.statementVisitorFactory)) + + fun withExpressionVisitor(factory: (Converter) -> ExpressionVisitor): Converter + = Converter(project, settings, conversionScope, State(typeConverter, state.methodReturnType, factory, state.statementVisitorFactory)) + + fun withStatementVisitor(factory: (Converter) -> StatementVisitor): Converter + = Converter(project, settings, conversionScope, State(typeConverter, state.methodReturnType, state.expressionVisitorFactory, factory)) + + public fun elementToKotlin(element: PsiElement): String { + val converted = convertTopElement(element) ?: return "" + val builder = CodeBuilder(element) + builder.append(converted) + return builder.result } - public fun clearClassIdentifiers() { - classIdentifiersSet.clear() - } - - public fun elementToKotlin(element: PsiElement): String - = convertTopElement(element)?.toKotlin() ?: "" - - private fun convertTopElement(element: PsiElement?): Element? = when(element) { + private fun convertTopElement(element: PsiElement?): Element? = when (element) { is PsiJavaFile -> convertFile(element) is PsiClass -> convertClass(element) is PsiMethod -> convertMethod(element, HashSet()) is PsiField -> convertField(element) is PsiStatement -> convertStatement(element) is PsiExpression -> convertExpression(element) - is PsiComment -> Comment(element.getText()!!) is PsiImportList -> convertImportList(element) is PsiImportStatementBase -> convertImport(element, false) - is PsiPackageStatement -> PackageStatement(quoteKeywords(element.getPackageName() ?: "")) - is PsiWhiteSpace -> WhiteSpace(element.getText()!!) + is PsiAnnotation -> convertAnnotation(element, false) + is PsiPackageStatement -> PackageStatement(quoteKeywords(element.getPackageName() ?: "")).assignPrototype(element) else -> null } - public fun convertFile(javaFile: PsiJavaFile): File { - val fileMembers = FileMemberList(javaFile.getChildren().map { convertTopElement(it) }.filterNotNull()) - return File(fileMembers, createMainFunction(javaFile)) + fun convertFile(javaFile: PsiJavaFile): File { + var convertedChildren = javaFile.getChildren().map { + if (it is PsiImportList) { + val importList = convertImportList(it) + typeConverter.importList = importList + importList + } + else { + convertTopElement(it) + } + }.filterNotNull() + + typeConverter.importList = null + if (typeConverter.importsToAdd.isNotEmpty()) { + val importList = convertedChildren.filterIsInstance(javaClass()).first() + val newImportList = ImportList(importList.imports + typeConverter.importsToAdd).assignPrototypesFrom(importList) + convertedChildren = convertedChildren.map { if (it == importList) newImportList else it } + } + + return File(convertedChildren, createMainFunction(javaFile)).assignPrototype(javaFile) } - public fun convertAnonymousClass(anonymousClass: PsiAnonymousClass): AnonymousClass { - return AnonymousClass(this, convertClassBody(anonymousClass)) + fun convertAnonymousClassBody(anonymousClass: PsiAnonymousClass): AnonymousClassBody { + return AnonymousClassBody(convertBody(anonymousClass), anonymousClass.getBaseClassType().resolve()?.isInterface() ?: false).assignPrototype(anonymousClass) } - private fun convertClassBody(psiClass: PsiClass): List { + private fun convertBody(psiClass: PsiClass): ClassBody { val membersToRemove = HashSet() - val convertedMembers = LinkedHashMap() - var inBody = false - val lBrace = psiClass.getLBrace() + val convertedMembers = LinkedHashMap() for (element in psiClass.getChildren()) { - if (element == lBrace) inBody = true - if (inBody) { - convertedMembers.put(element, convertMember(element, membersToRemove)) + if (element is PsiMember) { + val converted = convertMember(element, membersToRemove) + if (!converted.isEmpty) { + convertedMembers.put(element, converted) + } } } - return convertedMembers.keySet().filter { !membersToRemove.contains(it) }.map { convertedMembers[it]!! } - } - private fun convertMember(element: PsiElement, membersToRemove: MutableSet): Element = when(element) { - is PsiMethod -> convertMethod(element, membersToRemove) - is PsiField -> convertField(element) - is PsiClass -> convertClass(element) - is PsiClassInitializer -> convertInitializer(element) - else -> convertElement(element) - } - - private fun getComments(member: PsiMember): MemberComments { - var relevantChildren = member.getChildren().toList() - if (member is PsiClass) { - val leftBraceIndex = relevantChildren.indexOf(member.getLBrace()) - relevantChildren = relevantChildren.subList(0, leftBraceIndex) + for (member in membersToRemove) { + convertedMembers.remove(member) } - val whiteSpacesAndComments = relevantChildren - .filter { it is PsiWhiteSpace || it is PsiComment } - .map { convertElement(it) } - return MemberComments(whiteSpacesAndComments) + + val primaryConstructor = convertedMembers.values().filterIsInstance(javaClass()).firstOrNull() + val secondaryConstructors = convertedMembers.values().filterIsInstance(javaClass()) + + val useClassObject = shouldGenerateClassObject(psiClass, convertedMembers) + + val normalMembers = ArrayList() + val classObjectMembers = ArrayList() + for ((psiMember, member) in convertedMembers) { + if (member is Constructor) continue + if (useClassObject && psiMember !is PsiClass && psiMember.hasModifierProperty(PsiModifier.STATIC)) { + classObjectMembers.add(member) + } + else { + normalMembers.add(member) + } + } + + val lBrace = LBrace().assignPrototype(psiClass.getLBrace()) + val rBrace = RBrace().assignPrototype(psiClass.getRBrace()) + return ClassBody(primaryConstructor, secondaryConstructors, normalMembers, classObjectMembers, lBrace, rBrace) + } + + // do not convert private static methods into class object if possible + private fun shouldGenerateClassObject(psiClass: PsiClass, convertedMembers: Map): Boolean { + if (psiClass.isEnum()) return false + val members = convertedMembers.keySet().filter { !it.isConstructor() } + val classObjectMembers = members.filter { it !is PsiClass && it.hasModifierProperty(PsiModifier.STATIC) } + val nestedClasses = members.filterIsInstance(javaClass()).filter { it.hasModifierProperty(PsiModifier.STATIC) } + if (classObjectMembers.all { it is PsiMethod && it.hasModifierProperty(PsiModifier.PRIVATE) }) { + return nestedClasses.any { nestedClass -> classObjectMembers.any { findMethodCalls(it as PsiMethod, nestedClass).isNotEmpty() } } + } + else { + return true + } + } + + private fun convertMember(member: PsiMember, membersToRemove: MutableSet): Member = when (member) { + is PsiMethod -> convertMethod(member, membersToRemove) + is PsiField -> convertField(member) + is PsiClass -> convertClass(member) + is PsiClassInitializer -> convertInitializer(member) + else -> throw IllegalArgumentException("Unknown member: $member") } private fun convertClass(psiClass: PsiClass): Class { - val modifiers = convertModifiers(psiClass) + val annotations = convertAnnotations(psiClass) + var modifiers = convertModifiers(psiClass) val typeParameters = convertTypeParameterList(psiClass.getTypeParameterList()) val implementsTypes = convertToNotNullableTypes(psiClass.getImplementsListTypes()) val extendsTypes = convertToNotNullableTypes(psiClass.getExtendsListTypes()) - val name = Identifier(psiClass.getName()!!) - val classBodyElements = ArrayList(convertClassBody(psiClass)) + val name = psiClass.declarationIdentifier() + var classBody = convertBody(psiClass) - when { - psiClass.isInterface() -> return Trait(this, name, getComments(psiClass), modifiers, typeParameters, extendsTypes, listOf(), implementsTypes, classBodyElements) + return when { + psiClass.isInterface() -> Trait(name, annotations, modifiers, typeParameters, extendsTypes, listOf(), implementsTypes, classBody) - psiClass.isEnum() -> return Enum(this, name, getComments(psiClass), modifiers, typeParameters, listOf(), listOf(), implementsTypes, classBodyElements) + psiClass.isEnum() -> Enum(name, annotations, modifiers, typeParameters, listOf(), listOf(), implementsTypes, classBody) else -> { if (psiClass.getPrimaryConstructor() == null && psiClass.getConstructors().size > 1) { - generateArtificialPrimaryConstructor(name, classBodyElements) + classBody = generateArtificialPrimaryConstructor(name, classBody) } val baseClassParams: List = run { @@ -140,108 +198,156 @@ public class Converter(val project: Project, val settings: ConverterSettings) { } if (settings.openByDefault && !psiClass.hasModifierProperty(PsiModifier.FINAL)) { - modifiers.add(Modifier.OPEN) + modifiers = modifiers.with(Modifier.OPEN) } - return Class(this, name, getComments(psiClass), modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, classBodyElements) + if (psiClass.getContainingClass() != null && !psiClass.hasModifierProperty(PsiModifier.STATIC)) { + modifiers = modifiers.with(Modifier.INNER) + } + + Class(name, annotations, modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, classBody) } - } + }.assignPrototype(psiClass) } - private fun generateArtificialPrimaryConstructor(className: Identifier, classBodyElements: MutableList) { - val finalOrWithEmptyInitializerFields = classBodyElements.filterIsInstance(javaClass()).filter { it.isVal || it.initializer.toKotlin().isEmpty() } - val initializers = HashMap() - for (element in classBodyElements) { - if (element is SecondaryConstructor) { - for (field in finalOrWithEmptyInitializerFields) { - initializers.put(field.identifier.toKotlin(), getDefaultInitializer(field)) - } + private fun generateArtificialPrimaryConstructor(className: Identifier, classBody: ClassBody): ClassBody { + assert(classBody.primaryConstructor == null) - val newStatements = ArrayList() - for (statement in element.block!!.statements) { - var keepStatement = true - if (statement is AssignmentExpression) { - val assignee = statement.left - if (assignee is QualifiedExpression) { - for (field in finalOrWithEmptyInitializerFields) { - val id = field.identifier.toKotlin() - if (assignee.identifier.toKotlin().endsWith("." + id)) { - initializers.put(id, statement.right.toKotlin()) - keepStatement = false - } - - } - } - - } - - if (keepStatement) { - newStatements.add(statement) - } - - } - newStatements.add(0, DummyStringExpression("val __ = " + createPrimaryConstructorInvocation(className.toKotlin(), finalOrWithEmptyInitializerFields, initializers))) - element.block = Block(newStatements) + val finalOrWithEmptyInitializerFields = classBody.normalMembers.filterIsInstance(javaClass()).filter { it.isVal || it.initializer.isEmpty } + val initializers = HashMap() + for (constructor in classBody.secondaryConstructors) { + for (field in finalOrWithEmptyInitializerFields) { + initializers.put(field, getDefaultInitializer(field)) } + + val newStatements = ArrayList() + for (statement in constructor.block!!.statements) { + var keepStatement = true + if (statement is AssignmentExpression) { + val assignee = statement.left + if (assignee is QualifiedExpression && (assignee.qualifier as? Identifier)?.name == SecondaryConstructor.tempValIdentifier.name) { + val name = (assignee.identifier as Identifier).name + for (field in finalOrWithEmptyInitializerFields) { + if (name == field.identifier.name) { + initializers.put(field, statement.right) + keepStatement = false + } + + } + } + + } + + if (keepStatement) { + newStatements.add(statement) + } + + } + + val initializer = MethodCallExpression.buildNotNull(null, className.name, finalOrWithEmptyInitializerFields.map { initializers[it]!! }) + val localVar = LocalVariable(SecondaryConstructor.tempValIdentifier, + Annotations.Empty, + Modifiers.Empty, + { ClassType(className, listOf(), Nullability.NotNull, settings) }, + initializer, + true, + settings) + newStatements.add(0, DeclarationStatement(listOf(localVar))) + constructor.block = Block(newStatements, LBrace(), RBrace()) } //TODO: comments? val parameters = finalOrWithEmptyInitializerFields.map { field -> val varValModifier = if (field.isVal) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var - Parameter(field.identifier, field.`type`, varValModifier, field.modifiers.filter { ACCESS_MODIFIERS.contains(it) }) + Parameter(field.identifier, field.`type`, varValModifier, field.annotations, field.modifiers.filter { it in ACCESS_MODIFIERS }) } - classBodyElements.add(PrimaryConstructor(this, - MemberComments.Empty, - setOf(Modifier.PRIVATE), - ParameterList(parameters), - Block.Empty)) - classBodyElements.removeAll(finalOrWithEmptyInitializerFields) + + val primaryConstructor = PrimaryConstructor(this, Annotations.Empty, Modifiers(listOf(Modifier.PRIVATE)), ParameterList(parameters), Block.Empty) + val updatedMembers = classBody.normalMembers.filter { !finalOrWithEmptyInitializerFields.contains(it) } + return ClassBody(primaryConstructor, classBody.secondaryConstructors, updatedMembers, classBody.classObjectMembers, classBody.lBrace, classBody.rBrace) } private fun convertInitializer(initializer: PsiClassInitializer): Initializer { - return Initializer(convertBlock(initializer.getBody()), convertModifiers(initializer)) + return Initializer(convertBlock(initializer.getBody()), convertModifiers(initializer)).assignPrototype(initializer) } - private fun convertField(field: PsiField): Field { + private fun convertField(field: PsiField): Member { + val annotations = convertAnnotations(field) val modifiers = convertModifiers(field) - if (field is PsiEnumConstant) { - return EnumConstant(Identifier(field.getName()!!), - getComments(field), - modifiers, - typeConverter.convertType(field.getType(), Nullability.NotNull), - convertElement(field.getArgumentList())) + val name = field.declarationIdentifier() + val converted = if (field is PsiEnumConstant) { + EnumConstant(name, + annotations, + modifiers, + typeConverter.convertType(field.getType(), Nullability.NotNull), + convertElement(field.getArgumentList())) } + else { + val initializer = field.getInitializer() + val convertedType = typeConverter.convertVariableType(field) + val isVal = isVal(field) + val omitType = !settings.specifyFieldTypeByDefault && + initializer != null && + (modifiers.isPrivate && (isVal || convertedType == typeConverter.convertExpressionType(initializer)) || + modifiers.isInternal && convertedType == typeConverter.convertExpressionType(initializer)) + Field(name, + annotations, + modifiers, + convertedType, + convertExpression(initializer, field.getType()), + isVal, + !omitType, + field.hasWriteAccesses(field.getContainingClass())) + } + return converted.assignPrototype(field) + } - return Field(Identifier(field.getName()!!), - getComments(field), - modifiers, - typeConverter.convertVariableType(field), - convertExpression(field.getInitializer(), field.getType()), - field.hasModifierProperty(PsiModifier.FINAL), - field.hasWriteAccesses(field.getContainingClass())) + private fun isVal(field: PsiField): Boolean { + if (field.hasModifierProperty(PsiModifier.FINAL)) return true + if (!field.hasModifierProperty(PsiModifier.PRIVATE)) return false + val containingClass = field.getContainingClass() ?: return false + val writes = findVariableUsages(field, containingClass).filter { PsiUtil.isAccessedForWriting(it) } + if (writes.size == 0) return true + if (writes.size > 1) return false + val write = writes.single() + val parent = write.getParent() + if (parent is PsiAssignmentExpression && + parent.getOperationSign().getTokenType() == JavaTokenType.EQ && + isQualifierEmptyOrThis(write)) { + val constructor = write.getContainingConstructor() + if (constructor != null && + constructor.getContainingClass() == containingClass && + parent.getParent() is PsiExpressionStatement && + parent.getParent()?.getParent() == constructor.getBody()) { + return true + } + } + return false } private fun convertMethod(method: PsiMethod, membersToRemove: MutableSet): Function { - methodReturnType = method.getReturnType() + return withMethodReturnType(method.getReturnType()).doConvertMethod(method, membersToRemove).assignPrototype(method) + } + + private fun doConvertMethod(method: PsiMethod, membersToRemove: MutableSet): Function { val returnType = typeConverter.convertMethodReturnType(method) - val modifiers = convertModifiers(method) - - val comments = getComments(method) + val annotations = convertAnnotations(method) + convertThrows(method) + var modifiers = convertModifiers(method) if (method.isConstructor()) { if (method.isPrimaryConstructor()) { - return convertPrimaryConstructor(method, modifiers, comments, membersToRemove) + return convertPrimaryConstructor(method, annotations, modifiers, membersToRemove) } else { val params = convertParameterList(method.getParameterList()) - return SecondaryConstructor(this, comments, modifiers, params, convertBlock(method.getBody())) + return SecondaryConstructor(this, annotations, modifiers, params, convertBlock(method.getBody())) } } else { val isOverride = isOverride(method) if (isOverride) { - modifiers.add(Modifier.OVERRIDE) + modifiers = modifiers.with(Modifier.OVERRIDE) } val containingClass = method.getContainingClass() @@ -249,31 +355,15 @@ public class Converter(val project: Project, val settings: ConverterSettings) { if (settings.openByDefault) { val isEffectivelyFinal = method.hasModifierProperty(PsiModifier.FINAL) || containingClass != null && (containingClass.hasModifierProperty(PsiModifier.FINAL) || containingClass.isEnum()) - if (!isEffectivelyFinal && !modifiers.contains(Modifier.ABSTRACT) && !modifiers.contains(Modifier.PRIVATE)) { - modifiers.add(Modifier.OPEN) + if (!isEffectivelyFinal && !modifiers.contains(Modifier.ABSTRACT) && !modifiers.isPrivate) { + modifiers = modifiers.with(Modifier.OPEN) } } var params = convertParameterList(method.getParameterList()) - - // if we override equals from Object, change parameter type to nullable - if (isOverride && method.getName() == "equals") { - val superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures() - val overridesMethodFromObject = superSignatures.any { - it.getMethod().getContainingClass()?.getQualifiedName() == JAVA_LANG_OBJECT - } - if (overridesMethodFromObject) { - val correctedParameter = Parameter(Identifier("other"), - ClassType(Identifier("Any"), listOf(), Nullability.Nullable, settings), - Parameter.VarValModifier.None, - listOf()) - params = ParameterList(listOf(correctedParameter)) - } - } - val typeParameterList = convertTypeParameterList(method.getTypeParameterList()) val block = convertBlock(method.getBody()) - return Function(this, Identifier(method.getName()), comments, modifiers, returnType, typeParameterList, params, block, containingClass?.isInterface() ?: false) + return Function(this, method.declarationIdentifier(), annotations, modifiers, returnType, typeParameterList, params, block, containingClass?.isInterface() ?: false) } } @@ -292,16 +382,16 @@ public class Converter(val project: Project, val settings: ConverterSettings) { it.getMethod().getContainingClass()?.getQualifiedName() == JAVA_LANG_OBJECT } if (overridesMethodFromObject) { - when(method.getName()) { + when (method.getName()) { "equals", "hashCode", "toString" -> return true // these methods from java.lang.Object exist in kotlin.Any else -> { val containing = method.getContainingClass() if (containing != null) { val hasOtherJavaSuperclasses = containing.getSuperTypes().any { - val canonicalText = it.getCanonicalText() //TODO: correctly check for kotlin class - canonicalText != JAVA_LANG_OBJECT && !getClassIdentifiers().contains(canonicalText) + val `class` = it.resolve() + `class` != null && `class`.getQualifiedName() != JAVA_LANG_OBJECT && !conversionScope.contains(`class`) } if (hasOtherJavaSuperclasses) return true } @@ -313,8 +403,8 @@ public class Converter(val project: Project, val settings: ConverterSettings) { } private fun convertPrimaryConstructor(constructor: PsiMethod, - modifiers: Set, - comments: MemberComments, + annotations: Annotations, + modifiers: Modifiers, membersToRemove: MutableSet): PrimaryConstructor { val params = constructor.getParameterList().getParameters() val parameterToField = HashMap>() @@ -346,31 +436,27 @@ public class Converter(val project: Project, val settings: ConverterSettings) { usageReplacementMap.put(parameter, field.getName()!!) } } - dispatcher.expressionVisitor = ExpressionVisitor(this, typeConverter, usageReplacementMap) - try { - convertBlock(body, false, { !statementsToRemove.contains(it) }) - } - finally { - dispatcher.expressionVisitor = ExpressionVisitor(this, typeConverter, mapOf()) - } + + withExpressionVisitor { ExpressionVisitor(it, usageReplacementMap) }.convertBlock(body, false, { !statementsToRemove.contains(it) }) } else { Block.Empty } - val parameterList = ParameterList(params.map { - if (!parameterToField.containsKey(it)) { - convertParameter(it) + val parameterList = ParameterList(params.map { parameter -> + if (!parameterToField.containsKey(parameter)) { + convertParameter(parameter) } else { - val (field, `type`) = parameterToField[it]!! - Parameter(Identifier(field.getName()!!), + val (field, `type`) = parameterToField[parameter]!! + Parameter(field.declarationIdentifier(), `type`, - if (field.hasModifierProperty(PsiModifier.FINAL)) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var, - convertModifiers(field).filter { ACCESS_MODIFIERS.contains(it) }) + if (isVal(field)) Parameter.VarValModifier.Val else Parameter.VarValModifier.Var, + convertAnnotations(parameter) + convertAnnotations(field), + convertModifiers(field).filter { it in ACCESS_MODIFIERS }).assignPrototypes(listOf(parameter, field), inheritBlankLinesBefore = false) } }) - return PrimaryConstructor(this, comments, modifiers, parameterList, block) + return PrimaryConstructor(this, annotations, modifiers, parameterList, block).assignPrototype(constructor) } private fun findBackingFieldForConstructorParameter(parameter: PsiParameter, constructor: PsiMethod): Pair? { @@ -380,7 +466,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) { if (refs.any { PsiUtil.isAccessedForWriting(it) }) return null - for(ref in refs) { + for (ref in refs) { val assignment = ref.getParent() as? PsiAssignmentExpression ?: continue if (assignment.getOperationSign().getTokenType() != JavaTokenType.EQ) continue val assignee = assignment.getLExpression() as? PsiReferenceExpression ?: continue @@ -404,71 +490,63 @@ public class Converter(val project: Project, val settings: ConverterSettings) { return null } - public fun convertBlock(block: PsiCodeBlock?, notEmpty: Boolean = true, statementFilter: (PsiStatement) -> Boolean = {true}): Block { + fun convertBlock(block: PsiCodeBlock?, notEmpty: Boolean = true, statementFilter: (PsiStatement) -> Boolean = { true }): Block { if (block == null) return Block.Empty - val filteredChildren = block.getChildren().filter { it !is PsiStatement || statementFilter(it) } - val statementList = StatementList(filteredChildren.map { if (it is PsiStatement) convertStatement(it) else convertElement(it) }) - return Block(statementList, notEmpty) + val lBrace = LBrace().assignPrototype(block.getLBrace()) + val rBrace = RBrace().assignPrototype(block.getRBrace()) + return Block(block.getStatements().filter(statementFilter).map { convertStatement(it) }, lBrace, rBrace, notEmpty).assignPrototype(block) } - public fun convertStatement(statement: PsiStatement?): Statement { + fun convertStatement(statement: PsiStatement?): Statement { if (statement == null) return Statement.Empty - val statementVisitor: StatementVisitor = StatementVisitor(this) + statementVisitor.reset() statement.accept(statementVisitor) - return statementVisitor.result + return statementVisitor.result.assignPrototype(statement) } - public fun convertExpressions(expressions: Array): List + fun convertExpressions(expressions: Array): List = expressions.map { convertExpression(it) } - public fun convertExpression(expression: PsiExpression?): Expression { + fun convertExpression(expression: PsiExpression?): Expression { if (expression == null) return Expression.Empty - val expressionVisitor = dispatcher.expressionVisitor + expressionVisitor.reset() expression.accept(expressionVisitor) - return expressionVisitor.result + return expressionVisitor.result.assignPrototype(expression) } - public fun convertElement(element: PsiElement?): Element { + fun convertElement(element: PsiElement?): Element { if (element == null) return Element.Empty - val elementVisitor = ElementVisitor(this, typeConverter) + val elementVisitor = ElementVisitor(this) element.accept(elementVisitor) - return elementVisitor.result + return elementVisitor.result.assignPrototype(element) } - fun convertElements(elements: Array): List { - val result = ArrayList() - for (element in elements) { - result.add(convertElement(element)) - } - return result - } - - public fun convertTypeElement(element: PsiTypeElement?): TypeElement - = TypeElement(if (element == null) Type.Empty else typeConverter.convertType(element.getType())) + fun convertTypeElement(element: PsiTypeElement?): TypeElement + = TypeElement(if (element == null) Type.Empty else typeConverter.convertType(element.getType())).assignPrototype(element) private fun convertToNotNullableTypes(types: Array): List = types.map { typeConverter.convertType(it, Nullability.NotNull) } - public fun convertParameterList(parameterList: PsiParameterList): ParameterList - = ParameterList(parameterList.getParameters().map { convertParameter(it) }) + fun convertParameterList(parameterList: PsiParameterList): ParameterList + = ParameterList(parameterList.getParameters().map { convertParameter(it) }).assignPrototype(parameterList) - public fun convertParameter(parameter: PsiParameter, - nullability: Nullability = Nullability.Default, - varValModifier: Parameter.VarValModifier = Parameter.VarValModifier.None, - modifiers: Collection = listOf()): Parameter { + fun convertParameter(parameter: PsiParameter, + nullability: Nullability = Nullability.Default, + varValModifier: Parameter.VarValModifier = Parameter.VarValModifier.None, + modifiers: Modifiers = Modifiers.Empty): Parameter { var `type` = typeConverter.convertVariableType(parameter) when (nullability) { Nullability.NotNull -> `type` = `type`.toNotNullType() Nullability.Nullable -> `type` = `type`.toNullableType() } - return Parameter(Identifier(parameter.getName()!!), `type`, varValModifier, modifiers) + return Parameter(parameter.declarationIdentifier(), `type`, varValModifier, convertAnnotations(parameter), modifiers).assignPrototype(parameter) } - public fun convertExpression(argument: PsiExpression?, expectedType: PsiType?): Expression { + fun convertExpression(argument: PsiExpression?, expectedType: PsiType?): Expression { if (argument == null) return Identifier.Empty var expression = convertExpression(argument) @@ -487,36 +565,116 @@ public class Converter(val project: Project, val settings: ConverterSettings) { if (isConversionNeeded(actualType, expectedType) && expression !is LiteralExpression) { val conversion = PRIMITIVE_TYPE_CONVERSIONS[expectedType?.getCanonicalText()] if (conversion != null) { - expression = MethodCallExpression.build(expression, conversion) + expression = MethodCallExpression.buildNotNull(expression, conversion) } } } - return expression + return expression.assignPrototype(argument) } - private fun createPrimaryConstructorInvocation(s: String, fields: List, initializers: Map): String { - return s + "(" + fields.map { initializers[it.identifier.toKotlin()] }.makeString(", ") + ")" - } - - public fun convertIdentifier(identifier: PsiIdentifier?): Identifier { + fun convertIdentifier(identifier: PsiIdentifier?): Identifier { if (identifier == null) return Identifier.Empty - return Identifier(identifier.getText()!!) + return Identifier(identifier.getText()!!).assignPrototype(identifier) } - public fun convertModifiers(owner: PsiModifierListOwner): MutableSet - = HashSet(MODIFIERS_MAP.filter { owner.hasModifierProperty(it.first) }.map { it.second }) + fun convertModifiers(owner: PsiModifierListOwner): Modifiers + = Modifiers(MODIFIERS_MAP.filter { owner.hasModifierProperty(it.first) }.map { it.second }).assignPrototype(owner.getModifierList(), false) private val MODIFIERS_MAP = listOf( PsiModifier.ABSTRACT to Modifier.ABSTRACT, - PsiModifier.STATIC to Modifier.STATIC, PsiModifier.PUBLIC to Modifier.PUBLIC, PsiModifier.PROTECTED to Modifier.PROTECTED, PsiModifier.PRIVATE to Modifier.PRIVATE ) + fun convertAnnotations(owner: PsiModifierListOwner): Annotations { + val modifierList = owner.getModifierList() + val annotations = modifierList?.getAnnotations()?.filter { it.getQualifiedName() !in ANNOTATIONS_TO_REMOVE } + if (annotations == null || annotations.isEmpty()) return Annotations.Empty + + val newLines = run { + if (!modifierList!!.isInSingleLine()) { + true + } + else { + var child: PsiElement? = modifierList + while (true) { + child = child!!.getNextSibling() + if (child == null || child!!.getTextLength() != 0) break + } + if (child is PsiWhiteSpace) !child!!.isInSingleLine() else false + } + } + + val list = annotations.map { convertAnnotation(it, owner is PsiLocalVariable) }.filterNotNull() //TODO: brackets are also needed for local classes + return Annotations(list, newLines) + } + + private fun convertAnnotation(annotation: PsiAnnotation, brackets: Boolean): Annotation? { + val qualifiedName = annotation.getQualifiedName() + if (qualifiedName == CommonClassNames.JAVA_LANG_DEPRECATED && annotation.getParameterList().getAttributes().isEmpty()) { + return Annotation(Identifier("deprecated"), listOf(null to LiteralExpression("\"\"")), brackets).assignPrototype(annotation) //TODO: insert comment + } + + val nameRef = annotation.getNameReferenceElement() + val name = Identifier((nameRef ?: return null).getText()!!).assignPrototype(nameRef) + val annotationClass = nameRef!!.resolve() as? PsiClass + val lastMethod = annotationClass?.getMethods()?.lastOrNull() + val arguments = annotation.getParameterList().getAttributes().flatMap { + val method = annotationClass?.findMethodsByName(it.getName() ?: "value", false)?.firstOrNull() + val expectedType = method?.getReturnType() + + val attrName = it.getName()?.let { Identifier(it) } + val value = it.getValue() + + val isVarArg = method == lastMethod /* converted to vararg in Kotlin */ + val attrValues = convertAttributeValue(value, expectedType, isVarArg, it.getName() == null) + + attrValues.map { attrName to it } + } + return Annotation(name, arguments, brackets).assignPrototype(annotation) + } + + private fun convertAttributeValue(value: PsiAnnotationMemberValue?, expectedType: PsiType?, isVararg: Boolean, isUnnamed: Boolean): List { + return when (value) { + is PsiExpression -> listOf(convertExpression(value as? PsiExpression, expectedType)) + + is PsiArrayInitializerMemberValue -> { + val componentType = (expectedType as? PsiArrayType)?.getComponentType() + val componentsConverted = value.getInitializers().map { convertAttributeValue(it, componentType, false, true).single() } + if (isVararg && isUnnamed) { + componentsConverted + } + else { + val expectedTypeConverted = typeConverter.convertType(expectedType) + if (expectedTypeConverted is ArrayType) { + val array = createArrayInitializerExpression(expectedTypeConverted, componentsConverted, needExplicitType = false) + listOf(if (isVararg) StarExpression(array) else array) + } + else { + listOf(DummyStringExpression(value.getText()!!)) + } + } + } + + else -> listOf(DummyStringExpression(value?.getText() ?: "")) + } + } + + private fun convertThrows(method: PsiMethod): Annotations { + val throwsList = method.getThrowsList() + val types = throwsList.getReferencedTypes() + if (types.isEmpty()) return Annotations.Empty + val annotation = Annotation(Identifier("throws"), + types.map { null to MethodCallExpression.buildNotNull(null, "javaClass", listOf(), listOf(typeConverter.convertType(it, Nullability.NotNull))) }, + false) + return Annotations(listOf(annotation.assignPrototype(throwsList)), + true) + } + private val TYPE_MAP: Map = mapOf( JAVA_LANG_BYTE to "byte", JAVA_LANG_SHORT to "short", @@ -541,6 +699,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) { val NOT_NULL_ANNOTATIONS: Set = setOf("org.jetbrains.annotations.NotNull", "com.sun.istack.internal.NotNull", "javax.annotation.Nonnull") val NULLABLE_ANNOTATIONS: Set = setOf("org.jetbrains.annotations.Nullable", "com.sun.istack.internal.Nullable", "javax.annotation.Nullable") +val ANNOTATIONS_TO_REMOVE: Set = HashSet(NOT_NULL_ANNOTATIONS + NULLABLE_ANNOTATIONS + listOf(CommonClassNames.JAVA_LANG_OVERRIDE)) val PRIMITIVE_TYPE_CONVERSIONS: Map = mapOf( "byte" to BYTE.asString(), diff --git a/j2k/src/org/jetbrains/jet/j2k/ConverterSettings.kt b/j2k/src/org/jetbrains/jet/j2k/ConverterSettings.kt index 736163d24bd..0b54d5e48f3 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ConverterSettings.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ConverterSettings.kt @@ -16,20 +16,19 @@ package org.jetbrains.jet.j2k -public class ConverterSettings( +public data class ConverterSettings( var forceNotNullTypes: Boolean, var forceLocalVariableImmutability: Boolean, var specifyLocalVariableTypeByDefault: Boolean, + var specifyFieldTypeByDefault: Boolean, var openByDefault: Boolean) { - public fun copy(): ConverterSettings - = ConverterSettings(forceNotNullTypes, forceLocalVariableImmutability, specifyLocalVariableTypeByDefault, openByDefault) - class object { public val defaultSettings: ConverterSettings = ConverterSettings( forceNotNullTypes = true, forceLocalVariableImmutability = true, specifyLocalVariableTypeByDefault = false, + specifyFieldTypeByDefault = false, openByDefault = false ) } diff --git a/j2k/src/org/jetbrains/jet/j2k/JavaToKotlinTranslator.kt b/j2k/src/org/jetbrains/jet/j2k/JavaToKotlinTranslator.kt index 4715ee6f6df..8c97cd0e710 100644 --- a/j2k/src/org/jetbrains/jet/j2k/JavaToKotlinTranslator.kt +++ b/j2k/src/org/jetbrains/jet/j2k/JavaToKotlinTranslator.kt @@ -19,14 +19,12 @@ package org.jetbrains.jet.j2k import com.intellij.core.JavaCoreApplicationEnvironment import com.intellij.core.JavaCoreProjectEnvironment import com.intellij.lang.java.JavaLanguage -import com.intellij.openapi.Disposable import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.PsiFileFactory import com.intellij.psi.PsiJavaFile -import org.jetbrains.jet.j2k.visitors.ClassVisitor import org.jetbrains.jet.utils.PathUtil import java.io.File import java.net.URLClassLoader @@ -40,8 +38,8 @@ public object JavaToKotlinTranslator { return PsiFileFactory.getInstance(javaCoreEnvironment?.getProject())?.createFileFromText("test.java", JavaLanguage.INSTANCE, text) } - fun createFile(project: Project, text: String): PsiFile? { - return PsiFileFactory.getInstance(project)?.createFileFromText("test.java", JavaLanguage.INSTANCE, text) + fun createFile(project: Project, text: String): PsiJavaFile { + return PsiFileFactory.getInstance(project)?.createFileFromText("test.java", JavaLanguage.INSTANCE, text) as PsiJavaFile } fun setUpJavaCoreEnvironment(): JavaCoreProjectEnvironment { @@ -88,19 +86,11 @@ public object JavaToKotlinTranslator { return null } - fun setClassIdentifiers(converter: Converter, psiFile: PsiElement) { - val c = ClassVisitor() - psiFile.accept(c) - converter.clearClassIdentifiers() - converter.setClassIdentifiers(HashSet(c.classIdentifiers)) - } - fun generateKotlinCode(javaCode: String): String { val file = createFile(javaCode) if (file is PsiJavaFile) { - val converter = Converter(file.getProject(), ConverterSettings.defaultSettings) - setClassIdentifiers(converter, file) - return prettify(converter.convertFile(file).toKotlin()) + val converter = Converter.create(file.getProject(), ConverterSettings.defaultSettings, FilesConversionScope(listOf(file))) + return prettify(converter.elementToKotlin(file)) } return "" } diff --git a/j2k/src/org/jetbrains/jet/j2k/MainMethodUtils.kt b/j2k/src/org/jetbrains/jet/j2k/MainMethodUtils.kt index efbb1142f45..c508d8dd507 100644 --- a/j2k/src/org/jetbrains/jet/j2k/MainMethodUtils.kt +++ b/j2k/src/org/jetbrains/jet/j2k/MainMethodUtils.kt @@ -38,7 +38,7 @@ fun createMainFunction(file: PsiFile): String { } if (classNamesWithMains.size() > 0) { - var className = classNamesWithMains.get(0).first + var className = classNamesWithMains[0].first return MessageFormat.format("fun main(args : Array) = {0}.main(args as Array?)", className) } diff --git a/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt b/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt index 3b379e08f97..4458f631e5c 100644 --- a/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt @@ -21,14 +21,31 @@ import org.jetbrains.jet.j2k.ast.Nullability import com.intellij.psi.* import org.jetbrains.jet.j2k.visitors.TypeVisitor import java.util.HashMap +import java.util.HashSet +import org.jetbrains.jet.j2k.ast.Import +import org.jetbrains.jet.j2k.ast.ImportList +import org.jetbrains.jet.j2k.ast.assignPrototype +import com.intellij.psi.CommonClassNames.JAVA_LANG_OBJECT -class TypeConverter(val settings: ConverterSettings) { +class TypeConverter(val settings: ConverterSettings, val conversionScope: ConversionScope) { private val nullabilityCache = HashMap() + private val classesToImport = HashSet() + + public var importList: ImportList? = null + set(value) { + $importList = value + importNames = importList?.imports?.mapTo(HashSet()) { it.name } ?: setOf() + + } + private var importNames: Set = setOf() + + public val importsToAdd: Collection + get() = classesToImport.map { Import(it) } public fun convertType(`type`: PsiType?, nullability: Nullability = Nullability.Default): Type { if (`type` == null) return Type.Empty - val result = `type`.accept(TypeVisitor(this))!! + val result = `type`.accept(TypeVisitor(this, importNames, classesToImport))!! return when (nullability) { Nullability.NotNull -> result.toNotNullType() Nullability.Nullable -> result.toNullableType() @@ -40,7 +57,7 @@ class TypeConverter(val settings: ConverterSettings) { = types.map { convertType(it) } public fun convertVariableType(variable: PsiVariable): Type - = convertType(variable.getType(), variableNullability(variable)) + = convertType(variable.getType(), variableNullability(variable)).assignPrototype(variable.getTypeElement()) public fun variableNullability(variable: PsiVariable): Nullability { val cached = nullabilityCache[variable] @@ -52,13 +69,27 @@ class TypeConverter(val settings: ConverterSettings) { private fun variableNullabilityNoCache(variable: PsiVariable): Nullability { if (variable is PsiEnumConstant) return Nullability.NotNull + if (variable.getType() is PsiPrimitiveType) return Nullability.NotNull var nullability = variable.nullabilityFromAnnotations() + if (nullability == Nullability.Default && variable is PsiParameter) { + val scope = variable.getDeclarationScope() + if (scope is PsiMethod) { + val paramIndex = scope.getParameterList().getParameters().indexOf(variable) + assert(paramIndex >= 0) + val superSignatures = scope.getHierarchicalMethodSignature().getSuperSignatures() + nullability = superSignatures.map { signature -> + val params = signature.getMethod().getParameterList().getParameters() + if (paramIndex < params.size) variableNullability(params[paramIndex]) else Nullability.Default + }.firstOrNull { it != Nullability.Default } ?: Nullability.Default + } + } + if (nullability == Nullability.Default) { val initializer = variable.getInitializer() if (initializer != null) { - val initializerNullability = initializer.nullability() + val initializerNullability = initializer.nullability(false) if (variable.isEffectivelyFinal()) { nullability = initializerNullability } @@ -68,6 +99,18 @@ class TypeConverter(val settings: ConverterSettings) { } } + if (!conversionScope.contains(variable)) { // do not analyze usages out of our conversion scope + if (variable is PsiParameter) { + // Object.equals corresponds to Any.equals which has nullable parameter: + val scope = variable.getDeclarationScope() + if (scope is PsiMethod && scope.getName() == "equals" && scope.getContainingClass()?.getQualifiedName() == JAVA_LANG_OBJECT) { + return Nullability.Nullable + } + } + + return nullability + } + if (nullability == Nullability.Default) { val scope = searchScope(variable) if (scope != null) { @@ -87,7 +130,7 @@ class TypeConverter(val settings: ConverterSettings) { for (call in findMethodCalls(method, scope)) { val args = call.getArgumentList().getExpressions() if (args.size == parameters.size) { - if (args[parameterIndex].nullability() == Nullability.Nullable) { + if (args[parameterIndex].nullability(false) == Nullability.Nullable) { nullability = Nullability.Nullable break } @@ -101,7 +144,7 @@ class TypeConverter(val settings: ConverterSettings) { } public fun convertMethodReturnType(method: PsiMethod): Type - = convertType(method.getReturnType(), methodNullability(method)) + = convertType(method.getReturnType(), methodNullability(method)).assignPrototype(method.getReturnTypeElement()) public fun methodNullability(method: PsiMethod): Nullability { val cached = nullabilityCache[method] @@ -112,12 +155,21 @@ class TypeConverter(val settings: ConverterSettings) { } private fun methodNullabilityNoCache(method: PsiMethod): Nullability { + if (method.getReturnType() is PsiPrimitiveType) return Nullability.NotNull + var nullability = method.nullabilityFromAnnotations() + if (nullability == Nullability.Default) { + val superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures() + nullability = superSignatures.map { methodNullability(it.getMethod()) }.firstOrNull { it != Nullability.Default } ?: Nullability.Default + } + + if (!conversionScope.contains(method)) return nullability // do not analyze body and usages of methods out of our conversion scope + if (nullability == Nullability.Default) { method.getBody()?.accept(object: JavaRecursiveElementVisitor() { override fun visitReturnStatement(statement: PsiReturnStatement) { - if (statement.getReturnValue()?.nullability() == Nullability.Nullable) { + if (statement.getReturnValue()?.nullability(false) == Nullability.Nullable) { nullability = Nullability.Nullable } } @@ -140,6 +192,10 @@ class TypeConverter(val settings: ConverterSettings) { return nullability } + public fun convertExpressionType(expression: PsiExpression): Type { + return convertType(expression.getType(), expression.nullability(true)) + } + private fun searchScope(element: PsiElement): PsiElement? { return when(element) { is PsiParameter -> element.getDeclarationScope() @@ -150,22 +206,39 @@ class TypeConverter(val settings: ConverterSettings) { } } - private fun PsiExpression.nullability(): Nullability { + private fun PsiExpression.nullability(useDeclarationsNullability: Boolean): Nullability { return when (this) { is PsiLiteralExpression -> if (getType() != PsiType.NULL) Nullability.NotNull else Nullability.Nullable is PsiNewExpression -> Nullability.NotNull is PsiConditionalExpression -> { - val nullability1 = getThenExpression()?.nullability() + val nullability1 = getThenExpression()?.nullability(useDeclarationsNullability) if (nullability1 == Nullability.Nullable) return Nullability.Nullable - val nullability2 = getElseExpression()?.nullability() + val nullability2 = getElseExpression()?.nullability(useDeclarationsNullability) if (nullability2 == Nullability.Nullable) return Nullability.Nullable if (nullability1 == Nullability.NotNull && nullability2 == Nullability.NotNull) return Nullability.NotNull Nullability.Default } - is PsiParenthesizedExpression -> getExpression()?.nullability() ?: Nullability.Default + is PsiParenthesizedExpression -> getExpression()?.nullability(useDeclarationsNullability) ?: Nullability.Default + + is PsiMethodCallExpression -> if (useDeclarationsNullability) { + val method = resolveMethod() + if (method != null) methodNullability(method) else Nullability.Default + } + else { + Nullability.Default + } + + is PsiReferenceExpression -> if (useDeclarationsNullability) { + val variable = resolve() as? PsiVariable + if (variable != null) variableNullability(variable) else Nullability.Default + } + else { + Nullability.Default + } + //TODO: some other cases @@ -176,7 +249,7 @@ class TypeConverter(val settings: ConverterSettings) { private fun isNullableFromUsage(usage: PsiExpression): Boolean { val parent = usage.getParent() ?: return false if (parent is PsiAssignmentExpression && parent.getOperationTokenType() == JavaTokenType.EQ && usage == parent.getLExpression()) { - return parent.getRExpression()?.nullability() == Nullability.Nullable + return parent.getRExpression()?.nullability(false) == Nullability.Nullable } else if (parent is PsiBinaryExpression) { val operationType = parent.getOperationTokenType() @@ -196,7 +269,6 @@ class TypeConverter(val settings: ConverterSettings) { return when(this) { is PsiLocalVariable -> !hasWriteAccesses(getContainingMethod()) is PsiField -> if (hasModifierProperty(PsiModifier.PRIVATE)) !hasWriteAccesses(getContainingClass()) else false - is PsiParameter -> true else -> false } } diff --git a/j2k/src/org/jetbrains/jet/j2k/Utils.kt b/j2k/src/org/jetbrains/jet/j2k/Utils.kt index d887d22b105..eee0ce84cfe 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Utils.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Utils.kt @@ -16,16 +16,14 @@ package org.jetbrains.jet.j2k -import org.jetbrains.jet.j2k.ast.Identifier -import org.jetbrains.jet.j2k.ast.Field import org.jetbrains.jet.lang.types.expressions.OperatorConventions -import org.jetbrains.jet.j2k.ast.Nullability import com.intellij.psi.* import com.intellij.psi.util.PsiUtil import com.intellij.psi.search.LocalSearchScope import com.intellij.psi.search.searches.ReferencesSearch +import org.jetbrains.jet.j2k.ast.* -fun quoteKeywords(packageName: String): String = packageName.split("\\.").map { Identifier(it).toKotlin() }.makeString(".") +fun quoteKeywords(packageName: String): String = packageName.split("\\.").map { Identifier.toKotlin(it) }.makeString(".") fun findVariableUsages(variable: PsiVariable, scope: PsiElement): Collection { return ReferencesSearch.search(variable, LocalSearchScope(scope)).findAll().filterIsInstance(javaClass()) @@ -59,19 +57,22 @@ fun PsiModifierListOwner.nullabilityFromAnnotations(): Nullability { Nullability.Default } -fun getDefaultInitializer(field: Field): String { - if (field.`type`.isNullable) { - return "null" +fun getDefaultInitializer(field: Field): Expression { + val t = field.`type` + if (t.isNullable) { + return LiteralExpression("null") } - else { - return when(field.`type`.toKotlin()) { - "Boolean" -> "false" - "Char" -> "' '" - "Double" -> "0." + OperatorConventions.DOUBLE + "()" - "Float" -> "0." + OperatorConventions.FLOAT + "()" - else -> "0" + + if (t is PrimitiveType) { + when(t.name.name) { + "Boolean" -> return LiteralExpression("false") + "Char" -> return LiteralExpression("' '") + "Double" -> return MethodCallExpression.buildNotNull(LiteralExpression("0"), OperatorConventions.DOUBLE.toString()) + "Float" -> return MethodCallExpression.buildNotNull(LiteralExpression("0"), OperatorConventions.FLOAT.toString()) } } + + return LiteralExpression("0") } fun isQualifierEmptyOrThis(ref: PsiReferenceExpression): Boolean { @@ -91,4 +92,4 @@ fun PsiElement.isInSingleLine(): Boolean { child = child!!.getNextSibling() } return true -} \ No newline at end of file +} diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Annotation.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Annotation.kt new file mode 100644 index 00000000000..57b51cc5775 --- /dev/null +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Annotation.kt @@ -0,0 +1,66 @@ +/* + * 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.j2k.ast + +import org.jetbrains.jet.j2k.* + +class Annotation(val name: Identifier, val arguments: List>, val brackets: Boolean) : Element() { + private fun CodeBuilder.surroundWithBrackets(action: () -> Unit) { + if (brackets) append("[") + action() + if (brackets) append("]") + } + + override fun generateCode(builder: CodeBuilder) { + if (arguments.isEmpty()) { + builder.surroundWithBrackets { builder.append(name) } + return + } + + builder.surroundWithBrackets { + builder.append(name) + .append("(") + .append(arguments.map { + { + if (it.first != null) { + builder append it.first!! append " = " append it.second + } + else { + builder append it.second + } + } + }, ", ") + .append(")") + } + } +} + +class Annotations(val annotations: List, val newLines: Boolean) : Element() { + private val br = if (newLines) "\n" else " " + + override fun generateCode(builder: CodeBuilder) { + if (annotations.isNotEmpty()) { + builder.append(annotations, br, "", br) + } + } + + fun plus(other: Annotations) = Annotations(annotations + other.annotations, newLines || other.newLines) + + class object { + val Empty = Annotations(listOf(), false) + } +} diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/AssertStatement.kt b/j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClassBody.kt similarity index 66% rename from j2k/src/org/jetbrains/jet/j2k/ast/AssertStatement.kt rename to j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClassBody.kt index a43fef22c9f..0c9d2c3b953 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/AssertStatement.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/AnonymousClassBody.kt @@ -16,13 +16,11 @@ package org.jetbrains.jet.j2k.ast +import org.jetbrains.jet.j2k.CodeBuilder -class AssertStatement(val condition: Expression, val detail: Expression) : Statement() { - override fun toKotlin(): String { - val lazyStringMessage = if (detail != Expression.Empty) - " {" + detail.toKotlin() + "}" - else - "" - return "assert(${condition.toKotlin()})$lazyStringMessage" +class AnonymousClassBody(body: ClassBody, val extendsTrait: Boolean) +: Class(Identifier.Empty, Annotations.Empty, Modifiers.Empty, TypeParameterList.Empty, listOf(), listOf(), listOf(), body) { + override fun generateCode(builder: CodeBuilder) { + body.append(builder, null) } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/ArrayWithoutInitializationExpression.kt b/j2k/src/org/jetbrains/jet/j2k/ast/ArrayWithoutInitializationExpression.kt index d1432a41e10..c9f5f003f75 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/ArrayWithoutInitializationExpression.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/ArrayWithoutInitializationExpression.kt @@ -16,52 +16,51 @@ package org.jetbrains.jet.j2k.ast -open class ArrayWithoutInitializationExpression(val `type`: Type, val expressions: List) : Expression() { - override fun toKotlin(): String { - if (`type` is ArrayType) { - return constructInnerType(`type`, expressions) - } +import org.jetbrains.jet.j2k.CodeBuilder +import org.jetbrains.jet.j2k.append - return getConstructorName(`type`, expressions.size() != 0) - } +class ArrayWithoutInitializationExpression(val `type`: ArrayType, val expressions: List) : Expression() { + override fun generateCode(builder: CodeBuilder) { + fun appendConstructorName(`type`: ArrayType, hasInit: Boolean): CodeBuilder = when (`type`.elementType) { + is PrimitiveType -> builder.append(`type`.toNotNullType()) - private fun constructInnerType(hostType: ArrayType, expressions: List): String { - if (expressions.size() == 1) { - return oneDim(hostType, expressions[0]) - } - - val innerType = hostType.elementType - if (expressions.size() > 1 && innerType is ArrayType) { - return oneDim(hostType, expressions[0], "{" + constructInnerType(innerType, expressions.subList(1, expressions.size())) + "}") - } - - return getConstructorName(hostType, expressions.size() != 0) - } - - class object { - private open fun oneDim(`type`: Type, size: Expression): String { - return oneDim(`type`, size, "") - } - - private open fun oneDim(`type`: Type, size: Expression, init: String): String { - return getConstructorName(`type`, !init.isEmpty()) + "(" + size.toKotlin() + init.withPrefix(", ") + ")" - } - - private open fun getConstructorName(`type`: Type, hasInit: Boolean): String { - return if (`type` is ArrayType) - when (`type`.elementType) { - is PrimitiveType -> - `type`.toNotNullType().toKotlin() - is ArrayType -> - if (hasInit) - `type`.toNotNullType().toKotlin() - else - "arrayOfNulls<" + `type`.elementType.toKotlin() + ">" - else -> - "arrayOfNulls<" + `type`.elementType.toKotlin() + ">" + is ArrayType -> + if (hasInit) { + builder.append(`type`.toNotNullType()) } - else - `type`.toNotNullType().toKotlin() + else { + builder.append("arrayOfNulls<").append(`type`.elementType).append(">") + } + + else -> builder.append("arrayOfNulls<").append(`type`.elementType).append(">") } + + fun oneDim(`type`: ArrayType, size: Expression, init: (() -> Unit)? = null): CodeBuilder { + appendConstructorName(`type`, init != null).append("(").append(size) + if (init != null) { + builder.append(", ") + init() + } + return builder.append(")") + } + + fun constructInnerType(hostType: ArrayType, expressions: List): CodeBuilder { + if (expressions.size() == 1) { + return oneDim(hostType, expressions[0]) + } + + val innerType = hostType.elementType + if (expressions.size() > 1 && innerType is ArrayType) { + return oneDim(hostType, expressions[0], { + builder.append("{") + constructInnerType(innerType, expressions.subList(1, expressions.size())) + builder.append("}") + }) + } + + return appendConstructorName(hostType, expressions.isNotEmpty()) + } + + constructInnerType(`type`, expressions) } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Block.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Block.kt index 807e51a27f0..15b417ffe06 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Block.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Block.kt @@ -16,32 +16,35 @@ package org.jetbrains.jet.j2k.ast -import java.util.ArrayList - -fun Block(statements: List, notEmpty: Boolean = false): Block { - val elements = ArrayList() - elements.add(WhiteSpace.NewLine) - elements.addAll(statements) - elements.add(WhiteSpace.NewLine) - return Block(StatementList(elements), notEmpty) -} - -class Block(val statementList: StatementList, val notEmpty: Boolean = false) : Statement() { - val statements: List = statementList.statements - +import org.jetbrains.jet.j2k.* +class Block(val statements: List, val lBrace: LBrace, val rBrace: RBrace, val notEmpty: Boolean = false) : Statement() { override val isEmpty: Boolean get() = !notEmpty && statements.all { it.isEmpty } - override fun toKotlin(): String { - if (!isEmpty) { - return "{${statementList.toKotlin()}}" + override fun generateCode(builder: CodeBuilder) { + if (statements.all { it.isEmpty }) { + if (!isEmpty) builder.append(lBrace).append(rBrace) + return } - return "" + builder.append(lBrace).append(statements, "\n", "\n", "\n").append(rBrace) } class object { - val Empty = Block(StatementList(listOf())) + val Empty = Block(listOf(), LBrace(), RBrace()) + } +} + +// we use LBrace and RBrace elements to better handle comments around them +class LBrace() : Element() { + override fun generateCode(builder: CodeBuilder) { + builder.append("{") + } +} + +class RBrace() : Element() { + override fun generateCode(builder: CodeBuilder) { + builder.append("}") } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt index 268fe1d8cfa..8c5fe900747 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Class.kt @@ -16,93 +16,54 @@ package org.jetbrains.jet.j2k.ast -import org.jetbrains.jet.j2k.Converter -import java.util.ArrayList +import org.jetbrains.jet.j2k.* open class Class( - val converter: Converter, val name: Identifier, - comments: MemberComments, - modifiers: Set, + annotations: Annotations, + modifiers: Modifiers, val typeParameterList: TypeParameterList, val extendsTypes: List, val baseClassParams: List, val implementsTypes: List, - val bodyElements: List -) : Member(comments, modifiers) { + val body: ClassBody +) : Member(annotations, modifiers) { - override fun toKotlin(): String = - commentsToKotlin() + - modifiersToKotlin() + - keyword + " " + name.toKotlin() + - typeParameterList.toKotlin() + - primaryConstructorSignatureToKotlin() + - implementTypesToKotlin() + - typeParameterList.whereToKotlin().withPrefix(" ") + - bodyToKotlin() + override fun generateCode(builder: CodeBuilder) { + builder.append(annotations) + .appendWithSpaceAfter(presentationModifiers()) + .append(keyword) + .append(" ") + .append(name) + .append(typeParameterList) + appendPrimaryConstructorSignature(builder) + appendBaseTypes(builder) + typeParameterList.appendWhere(builder) + body.append(builder, this) + } protected open val keyword: String get() = "class" - protected val classMembers: ClassMembers = ClassMembers.fromBodyElements(bodyElements) - - protected open fun primaryConstructorSignatureToKotlin(): String - = classMembers.primaryConstructor?.signatureToKotlin() ?: "()" - - protected fun primaryConstructorBodyToKotlin(): String { - val constructor = classMembers.primaryConstructor - if (constructor != null && !(constructor.block?.isEmpty ?: true)) { - return "\n" + constructor.bodyToKotlin() + "\n" - } - return "" + protected open fun appendPrimaryConstructorSignature(builder: CodeBuilder) { + body.primaryConstructor?.appendSignature(builder) ?: builder.append("()") } - private fun secondaryConstructorsAsStaticInitFunctions(): MemberList { - return MemberList(classMembers.secondaryConstructors.elements.map { if (it is SecondaryConstructor) it.toInitFunction(this) else it }) + protected fun appendBaseTypes(builder: CodeBuilder) { + builder.append(baseClassSignatureWithParams(builder) + implementsTypes.map { { builder.append(it) } }, ", ", ":") } - private fun baseClassSignatureWithParams(): List { + private fun baseClassSignatureWithParams(builder: CodeBuilder): List<() -> CodeBuilder> { if (keyword.equals("class") && extendsTypes.size() == 1) { - val baseParams = baseClassParams.toKotlin(", ") - return arrayListOf(extendsTypes[0].toKotlin() + "(" + baseParams + ")") + return listOf({ + builder append extendsTypes[0] append "(" + builder.append(baseClassParams, ", ") + builder append ")" + }) } - return extendsTypes.map { it.toKotlin() } + return extendsTypes.map { { builder.append(it) } } } - protected fun implementTypesToKotlin(): String { - val allTypes = ArrayList() - allTypes.addAll(baseClassSignatureWithParams()) - allTypes.addAll(implementsTypes.map { it.toKotlin() }) - return if (allTypes.size() == 0) - "" - else - " : " + allTypes.makeString(", ") - } - - protected open fun modifiersToKotlin(): String { - val modifierList = ArrayList() - - modifiers.accessModifier()?.let { modifierList.add(it) } - - if (modifiers.contains(Modifier.ABSTRACT)) { - modifierList.add(Modifier.ABSTRACT) - } - else if (modifiers.contains(Modifier.OPEN)) { - modifierList.add(Modifier.OPEN) - } - - return modifierList.toKotlin() - } - - fun bodyToKotlin(): String { - val innerBody = classMembers.nonStaticMembers.toKotlin() + primaryConstructorBodyToKotlin() + classObjectToKotlin() - return if (innerBody.trim().isNotEmpty()) " {" + innerBody + "}" else "" - } - - private fun classObjectToKotlin(): String { - val secondaryConstructorsAsStaticInitFunctions = secondaryConstructorsAsStaticInitFunctions() - val staticMembers = classMembers.staticMembers - if (secondaryConstructorsAsStaticInitFunctions.isEmpty() && staticMembers.isEmpty()) return "" - return "\nclass object {${secondaryConstructorsAsStaticInitFunctions.toKotlin()}${staticMembers.toKotlin()}}" - } + protected open fun presentationModifiers(): Modifiers + = if (modifiers.contains(Modifier.ABSTRACT)) modifiers.without(Modifier.OPEN) else modifiers } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/ClassBody.kt b/j2k/src/org/jetbrains/jet/j2k/ast/ClassBody.kt new file mode 100644 index 00000000000..97b1100ce7f --- /dev/null +++ b/j2k/src/org/jetbrains/jet/j2k/ast/ClassBody.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2013 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.j2k.ast + +import org.jetbrains.jet.j2k.* + +abstract class Member(val annotations: Annotations, val modifiers: Modifiers) : Element() + +class ClassBody ( + val primaryConstructor: PrimaryConstructor?, + val secondaryConstructors: List, + val normalMembers: List, + val classObjectMembers: List, + val lBrace: LBrace, + val rBrace: RBrace) { + + fun append(builder: CodeBuilder, containingClass: Class?) { + if (normalMembers.isEmpty() && classObjectMembers.isEmpty() && secondaryConstructors.isEmpty() && (primaryConstructor?.block?.isEmpty ?: true)) return + + builder append " " append lBrace append "\n" + + builder.append(normalMembers, "\n") + var notEmpty = normalMembers.isNotEmpty() + + notEmpty = appendPrimaryConstructorBody(builder, notEmpty) || notEmpty + + appendClassObject(builder, containingClass, notEmpty) + + builder append "\n" append rBrace + } + + private fun appendPrimaryConstructorBody(builder: CodeBuilder, blankLineBefore: Boolean): Boolean { + val constructor = primaryConstructor + if (constructor == null || constructor.block?.isEmpty ?: true) return false + if (blankLineBefore) builder.append("\n\n") + constructor.appendBody(builder) + return true + } + + private fun appendClassObject(builder: CodeBuilder, containingClass: Class?, blankLineBefore: Boolean) { + if (secondaryConstructors.isEmpty() && classObjectMembers.isEmpty()) return + if (blankLineBefore) builder.append("\n\n") + val factoryFunctions = secondaryConstructors.map { it.toFactoryFunction(containingClass) } + builder.append(factoryFunctions + classObjectMembers, "\n", "class object {\n", "\n}") + } +} diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt index fd47996ca5e..5c29743fb18 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Constructors.kt @@ -16,51 +16,56 @@ package org.jetbrains.jet.j2k.ast -import org.jetbrains.jet.j2k.Converter -import java.util.HashSet import java.util.ArrayList +import org.jetbrains.jet.j2k.* abstract class Constructor( converter: Converter, - comments: MemberComments, - modifiers: Set, + annotations: Annotations, + modifiers: Modifiers, parameterList: ParameterList, block: Block -) : Function(converter, Identifier.Empty, comments, modifiers, Type.Empty, TypeParameterList.Empty, parameterList, block, false) +) : Function(converter, Identifier.Empty, annotations, modifiers, Type.Empty, TypeParameterList.Empty, parameterList, block, false) class PrimaryConstructor(converter: Converter, - comments: MemberComments, - modifiers: Set, + annotations: Annotations, + modifiers: Modifiers, parameterList: ParameterList, block: Block) - : Constructor(converter, comments, modifiers, parameterList, block) { + : Constructor(converter, annotations, modifiers, parameterList, block) { - public fun signatureToKotlin(): String { - val accessModifier = modifiers.accessModifier() - val modifiersString = if (accessModifier != null && accessModifier != Modifier.PUBLIC) " " + accessModifier.toKotlin() else "" - return modifiersString + "(" + parameterList.toKotlin() + ")" + public fun appendSignature(builder: CodeBuilder): CodeBuilder { + val accessModifier = modifiers.filter { it in ACCESS_MODIFIERS && it != Modifier.PUBLIC } + if (!accessModifier.isEmpty) { + builder append " " append accessModifier + } + return builder append "(" append parameterList append ")" } - public fun bodyToKotlin(): String = block!!.toKotlin() + public fun appendBody(builder: CodeBuilder): CodeBuilder = builder.append(block!!) } class SecondaryConstructor(converter: Converter, - comments: MemberComments, - modifiers: Set, + annotations: Annotations, + modifiers: Modifiers, parameterList: ParameterList, block: Block) - : Constructor(converter, comments, modifiers, parameterList, block) { + : Constructor(converter, annotations, modifiers, parameterList, block) { - public fun toInitFunction(containingClass: Class): Function { - val modifiers = HashSet(modifiers) - modifiers.add(Modifier.STATIC) + public fun toFactoryFunction(containingClass: Class?): Function { val statements = ArrayList(block?.statements ?: listOf()) - statements.add(ReturnStatement(Identifier("__"))) - val block = Block(statements) + statements.add(ReturnStatement(tempValIdentifier)) + val block = Block(statements, block?.lBrace ?: LBrace(), block?.rBrace ?: RBrace()) val typeParameters = ArrayList() - typeParameters.addAll(containingClass.typeParameterList.parameters) - return Function(converter, Identifier("init"), MemberComments.Empty, modifiers, - ClassType(containingClass.name, typeParameters, Nullability.NotNull, converter.settings), - TypeParameterList(typeParameters), parameterList, block, false) + if (containingClass != null) { + typeParameters.addAll(containingClass.typeParameterList.parameters) + } + return Function(converter, Identifier("create"), annotations, modifiers, + ClassType(containingClass?.name ?: Identifier.Empty, typeParameters, Nullability.NotNull, converter.settings), + TypeParameterList(typeParameters), parameterList, block, false).assignPrototypesFrom(this) + } + + class object { + public val tempValIdentifier: Identifier = Identifier("__", false) } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/DummyStringExpression.kt b/j2k/src/org/jetbrains/jet/j2k/ast/DummyStringExpression.kt index 607c7550262..106e841a940 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/DummyStringExpression.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/DummyStringExpression.kt @@ -16,7 +16,10 @@ package org.jetbrains.jet.j2k.ast +import org.jetbrains.jet.j2k.CodeBuilder -open class DummyStringExpression(val string: String) : Expression() { - override fun toKotlin(): String = string +class DummyStringExpression(val string: String) : Expression() { + override fun generateCode(builder: CodeBuilder) { + builder.append(string) + } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Element.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Element.kt index 4e4f0f2bed5..2a1b4f526b4 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Element.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Element.kt @@ -16,16 +16,47 @@ package org.jetbrains.jet.j2k.ast +import org.jetbrains.jet.j2k.* +import com.intellij.psi.PsiElement -trait Element : Node { - val isEmpty: Boolean get() = false +fun TElement.assignPrototype(prototype: PsiElement?, inheritBlankLinesBefore: Boolean = true): TElement { + assignPrototypeInfos(if (prototype != null) listOf(PrototypeInfo(prototype, inheritBlankLinesBefore)) else listOf()) + return this +} - object Empty : Element { - override fun toKotlin() = "" +fun TElement.assignPrototypes(prototypes: List, inheritBlankLinesBefore: Boolean): TElement { + assignPrototypeInfos(prototypes.map { PrototypeInfo(it, inheritBlankLinesBefore) }) + return this +} + +fun TElement.assignPrototypesFrom(element: Element): TElement { + assignPrototypeInfos(element.prototypes) + return this +} + +data class PrototypeInfo(val element: PsiElement, val inheritBlankLinesBefore: Boolean) + +fun Element.canonicalCode(): String { + val builder = CodeBuilder(null) + builder.append(this) + return builder.result +} + +abstract class Element { + public var prototypes: List = listOf() + private set + + public fun assignPrototypeInfos(prototypes: List) { + this.prototypes = prototypes + } + + /** This method should not be used anywhere except for CodeBuilder! Use CodeBuilder.append instead. */ + public abstract fun generateCode(builder: CodeBuilder) + + public open val isEmpty: Boolean get() = false + + object Empty : Element() { + override fun generateCode(builder: CodeBuilder) { } override val isEmpty: Boolean get() = true } } - -class Comment(val text: String) : Element { - override fun toKotlin() = text -} diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt index b30e6bfd203..04903876a46 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Enum.kt @@ -16,33 +16,29 @@ package org.jetbrains.jet.j2k.ast -import org.jetbrains.jet.j2k.Converter +import org.jetbrains.jet.j2k.* class Enum( - converter: Converter, name: Identifier, - comments: MemberComments, - modifiers: Set, + annotations: Annotations, + modifiers: Modifiers, typeParameterList: TypeParameterList, extendsTypes: List, baseClassParams: List, implementsTypes: List, - bodyElements: List -) : Class(converter, name, comments, modifiers, typeParameterList, - extendsTypes, baseClassParams, implementsTypes, bodyElements) { + body: ClassBody +) : Class(name, annotations, modifiers, typeParameterList, + extendsTypes, baseClassParams, implementsTypes, body) { - override fun primaryConstructorSignatureToKotlin(): String - = classMembers.primaryConstructor?.signatureToKotlin() ?: "" + override fun appendPrimaryConstructorSignature(builder: CodeBuilder) { + body.primaryConstructor?.appendSignature(builder) + } - override fun toKotlin(): String { - return modifiersToKotlin() + - "enum class " + name.toKotlin() + - primaryConstructorSignatureToKotlin() + - typeParameterList.toKotlin() + - implementTypesToKotlin() + - " {" + - classMembers.allMembers.toKotlin() + - primaryConstructorBodyToKotlin() + - "}" + override fun generateCode(builder: CodeBuilder) { + builder append annotations appendWithSpaceAfter presentationModifiers() append "enum class " append name + appendPrimaryConstructorSignature(builder) + builder append typeParameterList + appendBaseTypes(builder) + body.append(builder, this) } } \ No newline at end of file diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt b/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt index c850c968683..21c869e2e81 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/EnumConstant.kt @@ -16,20 +16,23 @@ package org.jetbrains.jet.j2k.ast -class EnumConstant( - identifier: Identifier, - members: MemberComments, - modifiers: Set, - `type`: Type, - params: Element -) : Field(identifier, members, modifiers, `type`.toNotNullType(), params, true, false) { +import org.jetbrains.jet.j2k.* - override fun toKotlin(): String { - if (initializer.toKotlin().isEmpty()) { - return identifier.toKotlin() +class EnumConstant( + val identifier: Identifier, + annotations: Annotations, + modifiers: Modifiers, + val `type`: Type, + val params: Element +) : Member(annotations, modifiers) { + + override fun generateCode(builder: CodeBuilder) { + if (params.isEmpty) { + builder append annotations append identifier + return } - return identifier.toKotlin() + " : " + `type`.toKotlin() + "(" + initializer.toKotlin() + ")" + builder append annotations append identifier append " : " append `type` append "(" append params append ")" } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Expression.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Expression.kt index 2152a1d6fa3..e9fa4713ae3 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Expression.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Expression.kt @@ -16,12 +16,14 @@ package org.jetbrains.jet.j2k.ast +import org.jetbrains.jet.j2k.CodeBuilder + abstract class Expression() : Statement() { open val isNullable: Boolean get() = false object Empty : Expression() { - override fun toKotlin() = "" + override fun generateCode(builder: CodeBuilder) {} override val isEmpty: Boolean get() = true } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/ExpressionList.kt b/j2k/src/org/jetbrains/jet/j2k/ast/ExpressionList.kt index 614dd5f9114..eaee0fe4c92 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/ExpressionList.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/ExpressionList.kt @@ -16,8 +16,12 @@ package org.jetbrains.jet.j2k.ast -open class ExpressionList(val expressions: List) : Expression() { - override fun toKotlin(): String = expressions.map { it.toKotlin() }.makeString(", ") +import org.jetbrains.jet.j2k.* + +class ExpressionList(val expressions: List) : Expression() { + override fun generateCode(builder: CodeBuilder) { + builder.append(expressions, ", ") + } override val isEmpty: Boolean get() = expressions.isEmpty() diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Expressions.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Expressions.kt index decdf5a7333..eee1b070edf 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Expressions.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Expressions.kt @@ -17,98 +17,144 @@ package org.jetbrains.jet.j2k.ast import org.jetbrains.jet.lang.types.expressions.OperatorConventions +import org.jetbrains.jet.j2k.* class ArrayAccessExpression(val expression: Expression, val index: Expression, val lvalue: Boolean) : Expression() { - override fun toKotlin() = operandToKotlin(expression) + - (if (!lvalue && expression.isNullable) "!!" else "") + - "[" + index.toKotlin() + "]" + override fun generateCode(builder: CodeBuilder) { + builder.appendOperand(this, expression) + if (!lvalue && expression.isNullable) builder.append("!!") + builder append "[" append index append "]" + } } class AssignmentExpression(val left: Expression, val right: Expression, val op: String) : Expression() { - override fun toKotlin() = operandToKotlin(left) + " " + op + " " + operandToKotlin(right) + override fun generateCode(builder: CodeBuilder) { + builder.appendOperand(this, left).append(" ").append(op).append(" ").appendOperand(this, right) + } } class BangBangExpression(val expr: Expression) : Expression() { - override fun toKotlin() = operandToKotlin(expr) + "!!" + override fun generateCode(builder: CodeBuilder) { + builder.appendOperand(this, expr).append("!!") + } } class BinaryExpression(val left: Expression, val right: Expression, val op: String) : Expression() { - override fun toKotlin() = operandToKotlin(left, false) + " " + op + " " + operandToKotlin(right, true) + override fun generateCode(builder: CodeBuilder) { + builder.appendOperand(this, left, false).append(" ").append(op).append(" ").appendOperand(this, right, true) + } } class IsOperator(val expression: Expression, val typeElement: TypeElement) : Expression() { - override fun toKotlin() = operandToKotlin(expression) + " is " + typeElement.toKotlinNotNull() + override fun generateCode(builder: CodeBuilder) { + builder.appendOperand(this, expression).append(" is ").append(typeElement.`type`.toNotNullType()) + } } class TypeCastExpression(val `type`: Type, val expression: Expression) : Expression() { - override fun toKotlin() = operandToKotlin(expression) + " as " + `type`.toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder.appendOperand(this, expression).append(" as ").append(`type`) + } } class LiteralExpression(val literalText: String) : Expression() { - override fun toKotlin() = literalText + override fun generateCode(builder: CodeBuilder) { + builder.append(literalText) + } } class ParenthesizedExpression(val expression: Expression) : Expression() { - override fun toKotlin() = "(" + expression.toKotlin() + ")" + override fun generateCode(builder: CodeBuilder) { + builder append "(" append expression append ")" + } } class PrefixOperator(val op: String, val expression: Expression) : Expression() { - override fun toKotlin() = op + operandToKotlin(expression) + override fun generateCode(builder: CodeBuilder){ + builder.append(op).appendOperand(this, expression) + } override val isNullable: Boolean get() = expression.isNullable } class PostfixOperator(val op: String, val expression: Expression) : Expression() { - override fun toKotlin() = operandToKotlin(expression) + op + override fun generateCode(builder: CodeBuilder) { + builder.appendOperand(this, expression) append op + } } class ThisExpression(val identifier: Identifier) : Expression() { - override fun toKotlin() = "this" + identifier.withPrefix("@") + override fun generateCode(builder: CodeBuilder) { + builder.append("this").appendWithPrefix(identifier, "@") + } } class SuperExpression(val identifier: Identifier) : Expression() { - override fun toKotlin() = "super" + identifier.withPrefix("@") + override fun generateCode(builder: CodeBuilder) { + builder.append("super").appendWithPrefix(identifier, "@") + } } -class QualifiedExpression(val expression: Expression, val identifier: Expression) : Expression() { +class QualifiedExpression(val qualifier: Expression, val identifier: Expression) : Expression() { override val isNullable: Boolean - get() { - if (!expression.isEmpty && expression.isNullable) return true - return identifier.isNullable + get() = identifier.isNullable + + override fun generateCode(builder: CodeBuilder) { + if (!qualifier.isEmpty) { + builder.appendOperand(this, qualifier).append(if (qualifier.isNullable) "!!." else ".") } - override fun toKotlin(): String { - if (!expression.isEmpty) { - return operandToKotlin(expression) + (if (expression.isNullable) "?." else ".") + identifier.toKotlin() - } - - return identifier.toKotlin() + builder.append(identifier) } } class PolyadicExpression(val expressions: List, val token: String) : Expression() { - override fun toKotlin(): String { - val expressionsWithConversions = expressions.map { it.toKotlin() } - return expressionsWithConversions.makeString(" " + token + " ") + override fun generateCode(builder: CodeBuilder) { + builder.append(expressions, " " + token + " ") } } -fun createArrayInitializerExpression(arrayType: ArrayType, initializers: List) : MethodCallExpression { - val elementType = arrayType.elementType - val createArrayFunction = if (elementType.isPrimitive()) { - (elementType.toNotNullType().toKotlin() + "Array").decapitalize() +class LambdaExpression(val arguments: String?, val block: Block) : Expression() { + override fun generateCode(builder: CodeBuilder) { + builder append block.lBrace append " " + + if (arguments != null) { + builder.append(arguments) + .append("->") + .append(if (block.statements.size > 1) "\n" else " ") + .append(block.statements, "\n") } + else { + builder.append(block.statements, "\n") + } + + builder append " " append block.rBrace + } +} + +class StarExpression(val methodCall: MethodCallExpression) : Expression() { + override fun generateCode(builder: CodeBuilder) { + builder append "*" append methodCall + } +} + +fun createArrayInitializerExpression(arrayType: ArrayType, initializers: List, needExplicitType: Boolean) : MethodCallExpression { + val elementType = arrayType.elementType + val createArrayFunction = if (elementType is PrimitiveType) + (elementType.toNotNullType().canonicalCode() + "Array").decapitalize() + else if (needExplicitType) + arrayType.toNotNullType().canonicalCode().decapitalize() else - arrayType.toNotNullType().toKotlin().decapitalize() + "array" val doubleOrFloatTypes = setOf("double", "float", "java.lang.double", "java.lang.float") - val afterReplace = arrayType.toNotNullType().toKotlin().replace("Array", "").toLowerCase().replace(">", "").replace("<", "").replace("?", "") + val afterReplace = arrayType.toNotNullType().canonicalCode().replace("Array", "").toLowerCase().replace(">", "").replace("<", "").replace("?", "") fun explicitConvertIfNeeded(initializer: Expression): Expression { if (doubleOrFloatTypes.contains(afterReplace)) { if (initializer is LiteralExpression) { - if (!initializer.toKotlin().contains(".")) { + if (!initializer.canonicalCode().contains(".")) { return LiteralExpression(initializer.literalText + ".0") } } @@ -119,7 +165,7 @@ fun createArrayInitializerExpression(arrayType: ArrayType, initializers: List null } if (conversionFunction != null) { - return MethodCallExpression(QualifiedExpression(initializer, Identifier(conversionFunction)), listOf(), listOf()) + return MethodCallExpression.buildNotNull(initializer, conversionFunction) } } } @@ -127,5 +173,5 @@ fun createArrayInitializerExpression(arrayType: ArrayType, initializers: List, + annotations: Annotations, + modifiers: Modifiers, val `type`: Type, val initializer: Element, val isVal: Boolean, + val explicitType: Boolean, private val hasWriteAccesses: Boolean -) : Member(comments, modifiers) { +) : Member(annotations, modifiers) { - override fun toKotlin(): String { - val declaration = commentsToKotlin() + modifiersToKotlin() + (if (isVal) "val " else "var ") + identifier.toKotlin() + " : " + `type`.toKotlin() - return if (initializer.isEmpty) - declaration + (if (isVal && !isStatic() && hasWriteAccesses) "" else " = " + getDefaultInitializer(this)) - else - declaration + " = " + initializer.toKotlin() - } + override fun generateCode(builder: CodeBuilder) { + builder.append(annotations) + .appendWithSpaceAfter(modifiers) + .append(if (isVal) "val " else "var ") + .append(identifier) - private fun modifiersToKotlin(): String { - val modifierList = ArrayList() - if (modifiers.contains(Modifier.ABSTRACT)) { - modifierList.add(Modifier.ABSTRACT) + if (explicitType) { + builder append ":" append `type` } - modifiers.accessModifier()?.let { modifierList.add(it) } - - return modifierList.toKotlin() + var initializerToUse = initializer + if (initializerToUse.isEmpty && !(isVal && hasWriteAccesses)) { + initializerToUse = getDefaultInitializer(this) + } + if (!initializerToUse.isEmpty) { + builder append " = " append initializerToUse + } } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/File.kt b/j2k/src/org/jetbrains/jet/j2k/ast/File.kt index 351fbf149ce..01ec9127bab 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/File.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/File.kt @@ -16,18 +16,21 @@ package org.jetbrains.jet.j2k.ast -class FileMemberList(elements: List) : WhiteSpaceSeparatedElementList(elements, WhiteSpace.NewLine, false) +import org.jetbrains.jet.j2k.CodeBuilder +import org.jetbrains.jet.j2k.append -class PackageStatement(val packageName: String) : Element { - override fun toKotlin(): String = "package " + packageName +class PackageStatement(val packageName: String) : Element() { + override fun generateCode(builder: CodeBuilder) { + builder append "package " append packageName + } } class File( - val body: FileMemberList, + val elements: List, val mainFunction: String -) : Element { +) : Element() { - override fun toKotlin(): String { - return body.toKotlin() + mainFunction + override fun generateCode(builder: CodeBuilder) { + builder.append(elements, "\n").append(mainFunction) } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt index a2f9a1e06e1..8e2bc8e0f68 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Function.kt @@ -16,53 +16,51 @@ package org.jetbrains.jet.j2k.ast -import java.util.ArrayList -import org.jetbrains.jet.j2k.Converter +import org.jetbrains.jet.j2k.* open class Function( val converter: Converter, val name: Identifier, - comments: MemberComments, - modifiers: Set, + annotations: Annotations, + modifiers: Modifiers, val `type`: Type, val typeParameterList: TypeParameterList, val parameterList: ParameterList, var block: Block?, val isInTrait: Boolean -) : Member(comments, modifiers) { +) : Member(annotations, modifiers) { - private fun modifiersToKotlin(): String { - val resultingModifiers = ArrayList() - val isOverride = modifiers.contains(Modifier.OVERRIDE) - if (isOverride) { - resultingModifiers.add(Modifier.OVERRIDE) + private fun presentationModifiers(): Modifiers { + var modifiers = this.modifiers + if (isInTrait) { + modifiers = modifiers.without(Modifier.ABSTRACT) } - val accessModifier = modifiers.accessModifier() - if (accessModifier != null && !isOverride) { - resultingModifiers.add(accessModifier) + if (modifiers.contains(Modifier.OVERRIDE)) { + modifiers = modifiers.filter { it != Modifier.OPEN && it !in ACCESS_MODIFIERS } } - if (modifiers.contains(Modifier.ABSTRACT) && !isInTrait) { - resultingModifiers.add(Modifier.ABSTRACT) - } - - if (modifiers.contains(Modifier.OPEN) && !isOverride) { - resultingModifiers.add(Modifier.OPEN) - } - - return resultingModifiers.toKotlin() + return modifiers } - private fun returnTypeToKotlin() = if (!`type`.isUnit()) " : " + `type`.toKotlin() + " " else " " + override fun generateCode(builder: CodeBuilder) { + builder.append(annotations) + .appendWithSpaceAfter(presentationModifiers()) + .append("fun ") + .appendWithSuffix(typeParameterList, " ") + .append(name) + .append("(") + .append(parameterList) + .append(")") - override fun toKotlin(): String { - return commentsToKotlin() + - modifiersToKotlin() + - "fun ${typeParameterList.toKotlin().withSuffix(" ")}${name.toKotlin()}" + - "(${parameterList.toKotlin()})" + - returnTypeToKotlin() + - typeParameterList.whereToKotlin() + - block?.toKotlin() + if (!`type`.isUnit()) { + builder append ":" append `type` + } + + typeParameterList.appendWhere(builder) + + if (block != null) { + builder append " " append block!! + } } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Identifier.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Identifier.kt index 35027e25253..6066082eda3 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Identifier.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Identifier.kt @@ -16,6 +16,13 @@ package org.jetbrains.jet.j2k.ast +import org.jetbrains.jet.j2k.CodeBuilder +import com.intellij.psi.PsiNameIdentifierOwner + +fun PsiNameIdentifierOwner.declarationIdentifier(): Identifier { + val name = getName() + return if (name != null) Identifier(name, false).assignPrototype(getNameIdentifier()!!) else Identifier.Empty +} class Identifier( val name: String, @@ -26,7 +33,7 @@ class Identifier( override val isEmpty: Boolean get() = name.isEmpty() - override fun toKotlin(): String { + private fun toKotlin(): String { if (quotingNeeded && ONLY_KOTLIN_KEYWORDS.contains(name) || name.contains("$")) { return quote(name) } @@ -34,13 +41,21 @@ class Identifier( return name } + override fun generateCode(builder: CodeBuilder) { + builder.append(toKotlin()) + } + private fun quote(str: String): String = "`" + str + "`" + override fun toString() = if (isNullable) "$name?" else name + class object { val Empty = Identifier("") val ONLY_KOTLIN_KEYWORDS: Set = setOf( "package", "as", "type", "val", "var", "fun", "is", "in", "object", "when", "trait", "This" - ); + ) + + fun toKotlin(name: String): String = Identifier(name).toKotlin() } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Imports.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Imports.kt index f939a873a5f..70d363d442f 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Imports.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Imports.kt @@ -24,40 +24,48 @@ import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap import com.intellij.psi.PsiJavaCodeReferenceElement import org.jetbrains.jet.asJava.KotlinLightClassForPackage -class Import(val name: String) : Element { - override fun toKotlin() = "import " + name +class Import(val name: String) : Element() { + override fun generateCode(builder: CodeBuilder) { + builder append "import " append name + } } -class ImportList(private val imports: List) : Element { +class ImportList(public val imports: List) : Element() { override val isEmpty: Boolean get() = imports.isEmpty() - override fun toKotlin() = imports.toKotlin("\n") + override fun generateCode(builder: CodeBuilder) { + builder.append(imports, "\n") + } } public fun Converter.convertImportList(importList: PsiImportList): ImportList = - ImportList(importList.getAllImportStatements().map { convertImport(it, true) }.filterNotNull()) + ImportList(importList.getAllImportStatements().map { convertImport(it, true) }.filterNotNull()).assignPrototype(importList) public fun Converter.convertImport(anImport: PsiImportStatementBase, filter: Boolean): Import? { - val reference = anImport.getImportReference() - if (reference == null) return null - val qualifiedName = quoteKeywords(reference.getQualifiedName()!!) - if (anImport.isOnDemand()) { - return Import(qualifiedName + ".*") - } - else { - return if (filter) { - val filteredName = filterImport(qualifiedName, reference) - if (filteredName != null) Import(filteredName) else null + fun doConvert(): Import? { + val reference = anImport.getImportReference() + if (reference == null) return null + val qualifiedName = quoteKeywords(reference.getQualifiedName()!!) + if (anImport.isOnDemand()) { + return Import(qualifiedName + ".*") } else { - Import(qualifiedName) + return if (filter) { + val filteredName = filterImport(qualifiedName, reference) + if (filteredName != null) Import(filteredName) else null + } + else { + Import(qualifiedName) + } } } + + return doConvert()?.assignPrototype(anImport) } private fun filterImport(name: String, ref: PsiJavaCodeReferenceElement): String? { - if (name in NOT_NULL_ANNOTATIONS || name in NULLABLE_ANNOTATIONS) return null + if (name in ANNOTATIONS_TO_REMOVE) return null // If imported class has a kotlin analog, drop the import if (!JavaToKotlinClassMap.getInstance().mapPlatformClass(FqName(name)).isEmpty()) return null diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Initializer.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Initializer.kt index f6616007bb1..4be86f4d9bf 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Initializer.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Initializer.kt @@ -16,10 +16,10 @@ package org.jetbrains.jet.j2k.ast +import org.jetbrains.jet.j2k.* -//TODO: is a member? -class Initializer(val block: Block, modifiers: Set) : Member(MemberComments.Empty, modifiers) { - override fun toKotlin(): String { - return block.toKotlin() +class Initializer(val block: Block, modifiers: Modifiers) : Member(Annotations.Empty, modifiers) { + override fun generateCode(builder: CodeBuilder) { + builder.append(block) } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt b/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt index d40d43fb34f..68cb7538eea 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/LocalVariable.kt @@ -17,27 +17,30 @@ package org.jetbrains.jet.j2k.ast import org.jetbrains.jet.j2k.ConverterSettings +import org.jetbrains.jet.j2k.CodeBuilder +import org.jetbrains.jet.j2k.append class LocalVariable( private val identifier: Identifier, - private val modifiers: Set, + private val annotations: Annotations, + private val modifiers: Modifiers, private val typeCalculator: () -> Type /* we use lazy type calculation for better performance */, private val initializer: Expression, private val isVal: Boolean, private val settings: ConverterSettings -) : Element { +) : Element() { - override fun toKotlin(): String { - val varVal = if (isVal) "val" else "var" - return if (initializer.isEmpty) { - "$varVal ${identifier.toKotlin()} : ${typeCalculator().toKotlin()}" + override fun generateCode(builder: CodeBuilder) { + builder.append(annotations).append(if (isVal) "val " else "var ") + if (initializer.isEmpty) { + builder append identifier append ":" append typeCalculator() } else { val shouldSpecifyType = settings.specifyLocalVariableTypeByDefault if (shouldSpecifyType) - "$varVal ${identifier.toKotlin()} : ${typeCalculator().toKotlin()} = ${initializer.toKotlin()}" + builder append identifier append ":" append typeCalculator() append " = " append initializer else - "$varVal ${identifier.toKotlin()} = ${initializer.toKotlin()}" + builder append identifier append " = " append initializer } } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Members.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Members.kt deleted file mode 100644 index 746eb79237d..00000000000 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Members.kt +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2010-2013 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.j2k.ast - -import java.util.ArrayList - -class MemberComments(elements: List) : WhiteSpaceSeparatedElementList(elements, WhiteSpace.NoSpace) { - class object { - val Empty = MemberComments(ArrayList()) - } -} - -abstract class Member(val comments: MemberComments, val modifiers: Set) : Element { - fun isStatic(): Boolean = modifiers.contains(Modifier.STATIC) - fun commentsToKotlin(): String = comments.toKotlin() -} - -//member itself and all the elements before it in the code (comments, whitespaces) -class MemberHolder(val member: Member, val elements: List) - -class MemberList(elements: List) : WhiteSpaceSeparatedElementList(elements, WhiteSpace.NewLine) { - val members: List - get() = elements.filter { it is Member }.map { it as Member } -} - -class ClassMembers private( - val primaryConstructor: PrimaryConstructor?, - val secondaryConstructors: MemberList, - val allMembers: MemberList, - val staticMembers: MemberList, - val nonStaticMembers: MemberList) { - class object { - public fun fromBodyElements(elements: List): ClassMembers { - val groups = splitInGroups(elements) - val constructors = groups.filter { it.member is Constructor } - val primaryConstructor = constructors.map { it.member }.filterIsInstance(javaClass()).firstOrNull() - val secondaryConstructors = constructors.filter { it.member is SecondaryConstructor } - val nonConstructors = groups.filter { it.member !is Constructor } - val staticMembers = nonConstructors.filter { it.member.isStatic() } - val nonStaticMembers = nonConstructors.filter { !it.member.isStatic() } - return ClassMembers(primaryConstructor, - secondaryConstructors.toMemberList(), - nonConstructors.toMemberList(), - staticMembers.toMemberList(), - nonStaticMembers.toMemberList()) - } - } -} - -private fun List.toMemberList() = MemberList(flatMap { it.elements }) - -private fun splitInGroups(elements: List): List { - val result = ArrayList>>() - var currentGroup = ArrayList() - for (element in elements) { - currentGroup.add(element) - if (element is Member) { - result.add(element to currentGroup) - currentGroup = ArrayList() - } - } - if (result.isNotEmpty()) { - result.last!!.second.addAll(currentGroup) - } - return result map { MemberHolder(it.first, it.second) } -} \ No newline at end of file diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/MethodCallExpression.kt b/j2k/src/org/jetbrains/jet/j2k/ast/MethodCallExpression.kt index 28aa928cea1..2ef4af8227a 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/MethodCallExpression.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/MethodCallExpression.kt @@ -16,30 +16,53 @@ package org.jetbrains.jet.j2k.ast -import java.util.ArrayList +import org.jetbrains.jet.j2k.* -open class MethodCallExpression( +class MethodCallExpression( val methodExpression: Expression, val arguments: List, - val typeParameters: List, - val resultIsNullable: Boolean = false + val typeArguments: List, + override val isNullable: Boolean, + val lambdaArgument: LambdaExpression? = null ) : Expression() { - override val isNullable: Boolean - get() = methodExpression.isNullable || resultIsNullable - - override fun toKotlin(): String { - val typeParamsToKotlin: String = typeParameters.toKotlin(", ", "<", ">") - val argumentsMapped = arguments.map { it.toKotlin() } - return operandToKotlin(methodExpression) + typeParamsToKotlin + "(" + argumentsMapped.makeString(", ") + ")" + override fun generateCode(builder: CodeBuilder) { + builder.appendOperand(this, methodExpression).append(typeArguments, ", ", "<", ">") + if (arguments.isNotEmpty() || lambdaArgument == null) { + builder.append("(").append(arguments, ", ").append(")") + } + if (lambdaArgument != null) { + builder.append(lambdaArgument) + } } class object { - public fun build(receiver: Expression, methodName: String, arguments: List = ArrayList()): MethodCallExpression { - return MethodCallExpression(QualifiedExpression(receiver, Identifier(methodName, false)), + public fun buildNotNull(receiver: Expression?, + methodName: String, + arguments: List = listOf(), + typeArguments: List = listOf(), + lambdaArgument: LambdaExpression? = null): MethodCallExpression + = build(receiver, methodName, arguments, typeArguments, false, lambdaArgument) + + public fun buildNullable(receiver: Expression?, + methodName: String, + arguments: List = listOf(), + typeArguments: List = listOf(), + lambdaArgument: LambdaExpression? = null): MethodCallExpression + = build(receiver, methodName, arguments, typeArguments, true, lambdaArgument) + + public fun build(receiver: Expression?, + methodName: String, + arguments: List, + typeArguments: List, + isNullable: Boolean, + lambdaArgument: LambdaExpression? = null): MethodCallExpression { + val identifier = Identifier(methodName, false) + return MethodCallExpression(if (receiver != null) QualifiedExpression(receiver, identifier) else identifier, arguments, - listOf(), - false) + typeArguments, + isNullable, + lambdaArgument) } } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt index 08883ac09fc..6335d18c1bc 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Modifier.kt @@ -16,14 +16,17 @@ package org.jetbrains.jet.j2k.ast +import org.jetbrains.jet.j2k.* +import java.util.HashSet + enum class Modifier(val name: String) { PUBLIC: Modifier("public") PROTECTED: Modifier("protected") PRIVATE: Modifier("private") - STATIC: Modifier("static") ABSTRACT: Modifier("abstract") OPEN: Modifier("open") OVERRIDE: Modifier("override") + INNER: Modifier("inner") public fun toKotlin(): String = name } @@ -31,10 +34,44 @@ enum class Modifier(val name: String) { val ACCESS_MODIFIERS = setOf(Modifier.PUBLIC, Modifier.PROTECTED, Modifier.PRIVATE) fun Collection.accessModifier(): Modifier? { - return firstOrNull { ACCESS_MODIFIERS.contains(it) } + return firstOrNull { it in ACCESS_MODIFIERS } } -fun Collection.toKotlin(): String - = if (isNotEmpty()) map { it.toKotlin() }.makeString(" ") + " " else "" +class Modifiers(val modifiers: Collection) : Element() { + override fun generateCode(builder: CodeBuilder) { + builder.append(modifiers.sortBy { it.ordinal() }.map { it.toKotlin() }.joinToString(" ")) + } + override val isEmpty: Boolean + get() = modifiers.isEmpty() + + fun with(modifier: Modifier): Modifiers = Modifiers(modifiers + listOf(modifier)).assignPrototypesFrom(this) + + fun without(modifier: Modifier): Modifiers { + val set = HashSet(modifiers) + set.remove(modifier) + return Modifiers(set).assignPrototypesFrom(this) + } + + fun contains(modifier: Modifier): Boolean = modifiers.contains(modifier) + + val isPublic: Boolean get() = contains(Modifier.PUBLIC) + val isPrivate: Boolean get() = contains(Modifier.PRIVATE) + val isProtected: Boolean get() = contains(Modifier.PROTECTED) + val isInternal: Boolean get() = !isPublic && !isPrivate && !isProtected + + class object { + val Empty = Modifiers(listOf()) + } +} + +fun Modifiers.filter(predicate: (Modifier) -> Boolean): Modifiers + = Modifiers(modifiers.filter(predicate)).assignPrototypesFrom(this) + +fun CodeBuilder.appendWithSpaceAfter(modifiers: Modifiers): CodeBuilder { + if (!modifiers.isEmpty) { + this append modifiers append " " + } + return this +} diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/NewClassExpression.kt b/j2k/src/org/jetbrains/jet/j2k/ast/NewClassExpression.kt index 45fff2a8fde..bf4b77386c8 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/NewClassExpression.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/NewClassExpression.kt @@ -16,20 +16,32 @@ package org.jetbrains.jet.j2k.ast -open class NewClassExpression( +import org.jetbrains.jet.j2k.* + +class NewClassExpression( val name: Element, val arguments: List, val qualifier: Expression = Expression.Empty, - val anonymousClass: AnonymousClass? = null + val anonymousClass: AnonymousClassBody? = null ) : Expression() { - override fun toKotlin(): String { - val callOperator = if (qualifier.isNullable) "?." else "." - val qualifier = if (qualifier.isEmpty) "" else qualifier.toKotlin() + callOperator - val appliedArguments = arguments.toKotlin(", ") - return if (anonymousClass != null) - "object : " + qualifier + name.toKotlin() + "(" + appliedArguments + ")" + anonymousClass.toKotlin() - else - qualifier + name.toKotlin() + "(" + appliedArguments + ")" + override fun generateCode(builder: CodeBuilder) { + if (anonymousClass != null) { + builder.append("object:") + } + + if (!qualifier.isEmpty) { + builder.append(qualifier).append(if (qualifier.isNullable) "!!." else ".") + } + + builder.append(name) + + if (anonymousClass == null || !anonymousClass.extendsTrait) { + builder.append("(").append(arguments, ", ").append(")") + } + + if (anonymousClass != null) { + builder.append(anonymousClass) + } } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Parameter.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Parameter.kt index 3e5758c0c12..ca5492bdbb1 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Parameter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Parameter.kt @@ -16,17 +16,21 @@ package org.jetbrains.jet.j2k.ast -class Parameter(val identifier: Identifier, val `type`: Type, val varVal: Parameter.VarValModifier, val modifiers: Collection) : Element { +import org.jetbrains.jet.j2k.* + +class Parameter(val identifier: Identifier, + val `type`: Type, + val varVal: Parameter.VarValModifier, + val annotations: Annotations, + val modifiers: Modifiers) : Element() { public enum class VarValModifier { None Val Var } - override fun toKotlin(): String { - val builder = StringBuilder() - - builder.append(modifiers.toKotlin()) + override fun generateCode(builder: CodeBuilder) { + builder.append(annotations).appendWithSpaceAfter(modifiers) if (`type` is VarArgType) { assert(varVal == VarValModifier.None) @@ -38,7 +42,6 @@ class Parameter(val identifier: Identifier, val `type`: Type, val varVal: Parame VarValModifier.Val -> builder.append("val ") } - builder.append(identifier.toKotlin()).append(": ").append(`type`.toKotlin()) - return builder.toString() + builder.append(identifier).append(":").append(`type`) } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/ParameterList.kt b/j2k/src/org/jetbrains/jet/j2k/ast/ParameterList.kt index d87508ec2c5..36d62b48e87 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/ParameterList.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/ParameterList.kt @@ -16,8 +16,11 @@ package org.jetbrains.jet.j2k.ast +import org.jetbrains.jet.j2k.* -open class ParameterList(val parameters: List) : Element { - override fun toKotlin() = parameters.map { it.toKotlin() }.makeString(", ") +class ParameterList(val parameters: List) : Element() { + override fun generateCode(builder: CodeBuilder) { + builder.append(parameters, ", ") + } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/ReferenceElement.kt b/j2k/src/org/jetbrains/jet/j2k/ast/ReferenceElement.kt index 4c551aa1176..9e03f71646f 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/ReferenceElement.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/ReferenceElement.kt @@ -16,6 +16,10 @@ package org.jetbrains.jet.j2k.ast -class ReferenceElement(val reference: Identifier, val types: List) : Element { - override fun toKotlin() = reference.toKotlin() + types.toKotlin(", ", "<", ">") +import org.jetbrains.jet.j2k.* + +class ReferenceElement(val reference: Identifier, val types: List) : Element() { + override fun generateCode(builder: CodeBuilder) { + builder.append(reference).append(types, ", ", "<", ">") + } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Statements.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Statements.kt index 3e1e786d122..91956cb8c85 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Statements.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Statements.kt @@ -16,10 +16,12 @@ package org.jetbrains.jet.j2k.ast +import org.jetbrains.jet.j2k.* -abstract class Statement() : Element { + +abstract class Statement() : Element() { object Empty : Statement() { - override fun toKotlin() = "" + override fun generateCode(builder: CodeBuilder) { } override val isEmpty: Boolean get() = true @@ -27,20 +29,27 @@ abstract class Statement() : Element { } class DeclarationStatement(val elements: List) : Statement() { - override fun toKotlin(): String - = elements.filterIsInstance(javaClass()).map { it.toKotlin() }.makeString("\n") + override fun generateCode(builder: CodeBuilder) { + builder.append(elements, "\n") + } } class ExpressionListStatement(val expressions: List) : Expression() { - override fun toKotlin() = expressions.toKotlin("\n") + override fun generateCode(builder: CodeBuilder) { + builder.append(expressions, "\n") + } } class LabelStatement(val name: Identifier, val statement: Element) : Statement() { - override fun toKotlin(): String = "@" + name.toKotlin() + " " + statement.toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder append "@" append name append " " append statement + } } class ReturnStatement(val expression: Expression) : Statement() { - override fun toKotlin() = "return " + expression.toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder append "return " append expression + } } class IfStatement( @@ -51,12 +60,11 @@ class IfStatement( ) : Expression() { private val br = if (singleLine) " " else "\n" - override fun toKotlin(): String { - val result = "if (" + condition.toKotlin() + ")$br" + thenStatement.toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder append "if (" append condition append ")" append br append thenStatement if (!elseStatement.isEmpty) { - return "$result${br}else$br${elseStatement.toKotlin()}" + builder append br append "else" append br append elseStatement } - return result } } @@ -65,13 +73,17 @@ class IfStatement( class WhileStatement(val condition: Expression, val body: Element, singleLine: Boolean) : Statement() { private val br = if (singleLine) " " else "\n" - override fun toKotlin() = "while (" + condition.toKotlin() + ")$br" + body.toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder append "while (" append condition append ")" append br append body + } } class DoWhileStatement(val condition: Expression, val body: Element, singleLine: Boolean) : Statement() { private val br = if (singleLine) " " else "\n" - override fun toKotlin() = "do$br" + body.toKotlin() + "${br}while (" + condition.toKotlin() + ")" + override fun generateCode(builder: CodeBuilder) { + builder append "do" append br append body append br append "while (" append condition append ")" + } } class ForeachStatement( @@ -83,7 +95,9 @@ class ForeachStatement( private val br = if (singleLine) " " else "\n" - override fun toKotlin() = "for (" + variable.identifier.toKotlin() + " in " + expression.toKotlin() + ")$br" + body.toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder append "for (" append variable.identifier append " in " append expression append ")" append br append body + } } class ForeachWithRangeStatement(val identifier: Identifier, @@ -93,70 +107,78 @@ class ForeachWithRangeStatement(val identifier: Identifier, singleLine: Boolean) : Statement() { private val br = if (singleLine) " " else "\n" - override fun toKotlin() = "for (" + identifier.toKotlin() + " in " + start.toKotlin() + ".." + end.toKotlin() + ")$br" + body.toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder append "for (" append identifier append " in " append start append ".." append end append ")" append br append body + } } class BreakStatement(val label: Identifier = Identifier.Empty) : Statement() { - override fun toKotlin() = "break" + label.withPrefix("@") + override fun generateCode(builder: CodeBuilder) { + builder.append("break").appendWithPrefix(label, "@") + } } class ContinueStatement(val label: Identifier = Identifier.Empty) : Statement() { - override fun toKotlin() = "continue" + label.withPrefix("@") + override fun generateCode(builder: CodeBuilder) { + builder.append("continue").appendWithPrefix(label, "@") + } } // Exceptions ---------------------------------------------------------------------------------------------- class TryStatement(val block: Block, val catches: List, val finallyBlock: Block) : Statement() { - override fun toKotlin(): String { - val builder = StringBuilder() - .append("try\n") - .append(block.toKotlin()) - .append("\n") - .append(catches.toKotlin("\n")) - .append("\n") + override fun generateCode(builder: CodeBuilder) { + builder.append("try\n").append(block).append("\n").append(catches, "\n").append("\n") if (!finallyBlock.isEmpty) { - builder.append("finally\n").append(finallyBlock.toKotlin()) + builder append "finally\n" append finallyBlock } - return builder.toString() } } class ThrowStatement(val expression: Expression) : Expression() { - override fun toKotlin() = "throw " + expression.toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder append "throw " append expression + } } class CatchStatement(val variable: Parameter, val block: Block) : Statement() { - override fun toKotlin(): String = "catch (" + variable.toKotlin() + ") " + block.toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder append "catch (" append variable append ") " append block + } } // Switch -------------------------------------------------------------------------------------------------- class SwitchContainer(val expression: Expression, val caseContainers: List) : Statement() { - override fun toKotlin() = "when (" + expression.toKotlin() + ") {\n" + caseContainers.toKotlin("\n") + "\n}" + override fun generateCode(builder: CodeBuilder) { + builder.append("when (").append(expression).append(") {\n").append(caseContainers, "\n").append("\n}") + } } class CaseContainer(val caseStatement: List, statements: List) : Statement() { - private val block = Block(statements.filterNot { it is BreakStatement || it is ContinueStatement }, true) + private val block = Block(statements.filterNot { it is BreakStatement || it is ContinueStatement }, LBrace(), RBrace(), true) - override fun toKotlin() = caseStatement.toKotlin(", ") + " -> " + block.toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder.append(caseStatement, ", ").append(" -> ").append(block) + } } class SwitchLabelStatement(val expression: Expression) : Statement() { - override fun toKotlin() = expression.toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder.append(expression) + } } class DefaultSwitchLabelStatement() : Statement() { - override fun toKotlin() = "else" + override fun generateCode(builder: CodeBuilder) { + builder.append("else") + } } // Other ------------------------------------------------------------------------------------------------------ class SynchronizedStatement(val expression: Expression, val block: Block) : Statement() { - override fun toKotlin() = "synchronized (" + expression.toKotlin() + ") " + block.toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder append "synchronized (" append expression append ") " append block + } } - -class StatementList(elements: List) - : WhiteSpaceSeparatedElementList(elements, WhiteSpace.NewLine) { - val statements: List - get() = elements.filterIsInstance(javaClass()) -} \ No newline at end of file diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt index 4238c0bde6d..034d5bdc5ad 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Trait.kt @@ -16,31 +16,23 @@ package org.jetbrains.jet.j2k.ast -import org.jetbrains.jet.j2k.Converter -import java.util.ArrayList +import org.jetbrains.jet.j2k.CodeBuilder -class Trait( - converter: Converter, - name: Identifier, - comments: MemberComments, - modifiers: Set, - typeParameterList: TypeParameterList, - extendsTypes: List, - baseClassParams: List, - implementsTypes: List, - bodyElements: List -) : Class(converter, name, comments, modifiers, typeParameterList, - extendsTypes, baseClassParams, implementsTypes, bodyElements) { +class Trait(name: Identifier, + annotations: Annotations, + modifiers: Modifiers, + typeParameterList: TypeParameterList, + extendsTypes: List, + baseClassParams: List, + implementsTypes: List, + body: ClassBody +) : Class(name, annotations, modifiers, typeParameterList, extendsTypes, baseClassParams, implementsTypes, body) { override val keyword: String get() = "trait" - override fun primaryConstructorSignatureToKotlin() = "" - - override fun modifiersToKotlin(): String { - val modifierList = ArrayList() - modifiers.accessModifier()?.let { modifierList.add(it) } - return modifierList.toKotlin() - } + override fun appendPrimaryConstructorSignature(builder: CodeBuilder) { } + override fun presentationModifiers(): Modifiers + = modifiers.filter { it in ACCESS_MODIFIERS } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/TypeElement.kt b/j2k/src/org/jetbrains/jet/j2k/ast/TypeElement.kt index 5b0e8cc1bc7..b33e322a564 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/TypeElement.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/TypeElement.kt @@ -16,8 +16,10 @@ package org.jetbrains.jet.j2k.ast -class TypeElement(val `type`: Type) : Element { - override fun toKotlin() = `type`.toKotlin() +import org.jetbrains.jet.j2k.* - fun toKotlinNotNull(): String = `type`.toNotNullType().toKotlin() +class TypeElement(val `type`: Type) : Element() { + override fun generateCode(builder: CodeBuilder) { + builder.append(`type`) + } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/TypeParameters.kt b/j2k/src/org/jetbrains/jet/j2k/ast/TypeParameters.kt index a1d3b5bd199..049d69702ee 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/TypeParameters.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/TypeParameters.kt @@ -17,42 +17,37 @@ package org.jetbrains.jet.j2k.ast import com.intellij.psi.PsiTypeParameter -import org.jetbrains.jet.j2k.Converter +import org.jetbrains.jet.j2k.* import com.intellij.psi.PsiTypeParameterList import java.util.ArrayList -class TypeParameter(val name: Identifier, val extendsTypes: List) : Element { +class TypeParameter(val name: Identifier, val extendsTypes: List) : Element() { fun hasWhere(): Boolean = extendsTypes.size() > 1 - fun getWhereToKotlin(): String { - if (hasWhere()) { - return name.toKotlin() + " : " + extendsTypes.get(1).toKotlin() - } - return "" + fun whereToKotlin(builder: CodeBuilder) { + if (hasWhere()) { + builder append name append " : " append extendsTypes[1] + } } - override fun toKotlin(): String { - if (extendsTypes.size() > 0) { - return name.toKotlin() + " : " + extendsTypes [0].toKotlin() + override fun generateCode(builder: CodeBuilder) { + builder append name + if (extendsTypes.isNotEmpty()) { + builder append " : " append extendsTypes[0] } - - return name.toKotlin() } } -class TypeParameterList(val parameters: List) : Element { - override fun toKotlin(): String = if (!parameters.isEmpty()) - parameters.map { - it.toKotlin() - }.makeString(", ", "<", ">") - else "" +class TypeParameterList(val parameters: List) : Element() { + override fun generateCode(builder: CodeBuilder) { + if (parameters.isNotEmpty()) builder.append(parameters, ", ", "<", ">") + } - fun whereToKotlin(): String { + fun appendWhere(builder: CodeBuilder): CodeBuilder { if (hasWhere()) { - val wheres = parameters.map { it.getWhereToKotlin() } - return "where " + wheres.makeString(", ") + builder.append( parameters.map { { it.whereToKotlin(builder) } }, ", ", " where ", "") } - return "" + return builder } @@ -70,7 +65,9 @@ fun Converter.convertTypeParameter(psiTypeParameter: PsiTypeParameter): TypePara return convertElement(psiTypeParameter) as TypeParameter } -fun Converter.convertTypeParameterList(psiTypeParameterlist: PsiTypeParameterList?): TypeParameterList { - return if (psiTypeParameterlist == null) TypeParameterList.Empty - else TypeParameterList(psiTypeParameterlist.getTypeParameters()!!.toList().map { convertTypeParameter(it) }) +fun Converter.convertTypeParameterList(typeParameterList: PsiTypeParameterList?): TypeParameterList { + return if (typeParameterList != null) + TypeParameterList(typeParameterList.getTypeParameters()!!.toList().map { convertTypeParameter(it) }) + else + TypeParameterList.Empty } \ No newline at end of file diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Types.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Types.kt index 122b3b90e7a..344a4e02bdf 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Types.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Types.kt @@ -16,10 +16,8 @@ package org.jetbrains.jet.j2k.ast -import java.util.ArrayList -import org.jetbrains.jet.j2k.ConverterSettings +import org.jetbrains.jet.j2k.* -fun Type.isPrimitive(): Boolean = this is PrimitiveType fun Type.isUnit(): Boolean = this == Type.Unit enum class Nullability { @@ -34,99 +32,105 @@ fun Nullability.isNullable(settings: ConverterSettings) = when(this) { Nullability.Default -> !settings.forceNotNullTypes } -abstract class MayBeNullableType(nullability: Nullability, val settings: ConverterSettings) : Type { +abstract class MayBeNullableType(nullability: Nullability, val settings: ConverterSettings) : Type() { override val isNullable: Boolean = nullability.isNullable(settings) + + protected val isNullableStr: String + get() = if (isNullable) "?" else "" } -trait NotNullType : Type { +abstract class NotNullType() : Type() { override val isNullable: Boolean get() = false } -trait Type : Element { - val isNullable: Boolean +abstract class Type() : Element() { + abstract val isNullable: Boolean - open fun toNotNullType(): Type { - if (isNullable) throw UnsupportedOperationException("toNotNullType must be defined") - return this + open fun toNotNullType(): Type = this + + open fun toNullableType(): Type = this + + object Empty : NotNullType() { + override fun generateCode(builder: CodeBuilder) { + builder.append("UNRESOLVED_TYPE") + } } - open fun toNullableType(): Type { - if (!isNullable) throw UnsupportedOperationException("toNullableType must be defined") - return this + object Unit: NotNullType() { + override fun generateCode(builder: CodeBuilder) { + builder.append("Unit") + } } - protected fun isNullableStr(): String? { - return if (isNullable) "?" else "" + object Null: Type() { + override val isNullable: Boolean = true + + override fun generateCode(builder: CodeBuilder) { + builder.append("???") + } } - object Empty : NotNullType { - override fun toKotlin(): String = "UNRESOLVED_TYPE" - } + override fun equals(other: Any?): Boolean = other is Type && other.canonicalCode() == this.canonicalCode() - object Unit: NotNullType { - override fun toKotlin() = "Unit" - } + override fun hashCode(): Int = canonicalCode().hashCode() - override fun equals(other: Any?): Boolean = other is Type && other.toKotlin() == this.toKotlin() - - override fun hashCode(): Int = toKotlin().hashCode() - - override fun toString(): String = toKotlin() + override fun toString(): String = canonicalCode() } -class ClassType(val `type`: Identifier, val parameters: List, nullability: Nullability, settings: ConverterSettings) +class ClassType(val name: Identifier, val typeArgs: List, nullability: Nullability, settings: ConverterSettings) : MayBeNullableType(nullability, settings) { - override fun toKotlin(): String { - // TODO change to map() when KT-2051 is fixed - val parametersToKotlin = ArrayList() - for (param in parameters) { - parametersToKotlin.add(param.toKotlin()) - } - var params: String = if (parametersToKotlin.size() == 0) - "" - else - "<" + parametersToKotlin.makeString(", ") + ">" - return `type`.toKotlin() + params + isNullableStr() + override fun generateCode(builder: CodeBuilder) { + builder.append(name).append(typeArgs, ", ", "<", ">").append(isNullableStr) } - - override fun toNotNullType(): Type = ClassType(`type`, parameters, Nullability.NotNull, settings) - override fun toNullableType(): Type = ClassType(`type`, parameters, Nullability.Nullable, settings) + override fun toNotNullType(): Type = ClassType(name, typeArgs, Nullability.NotNull, settings) + override fun toNullableType(): Type = ClassType(name, typeArgs, Nullability.Nullable, settings) } class ArrayType(val elementType: Type, nullability: Nullability, settings: ConverterSettings) : MayBeNullableType(nullability, settings) { - override fun toKotlin(): String { + override fun generateCode(builder: CodeBuilder) { if (elementType is PrimitiveType) { - return elementType.toKotlin() + "Array" + isNullableStr() + builder append elementType append "Array" append isNullableStr + } + else { + builder append "Array<" append elementType append ">" append isNullableStr } - - return "Array<" + elementType.toKotlin() + ">" + isNullableStr() } override fun toNotNullType(): Type = ArrayType(elementType, Nullability.NotNull, settings) override fun toNullableType(): Type = ArrayType(elementType, Nullability.Nullable, settings) } -class InProjectionType(val bound: Type) : NotNullType { - override fun toKotlin(): String = "in " + bound.toKotlin() +class InProjectionType(val bound: Type) : NotNullType() { + override fun generateCode(builder: CodeBuilder) { + builder append "in " append bound + } } -class OutProjectionType(val bound: Type) : NotNullType { - override fun toKotlin(): String = "out " + bound.toKotlin() +class OutProjectionType(val bound: Type) : NotNullType() { + override fun generateCode(builder: CodeBuilder) { + builder append "out " append bound + } } -class StarProjectionType() : NotNullType { - override fun toKotlin(): String = "*" +class StarProjectionType() : NotNullType() { + override fun generateCode(builder: CodeBuilder) { + builder.append("*") + } } -class PrimitiveType(val `type`: Identifier) : NotNullType { - override fun toKotlin(): String = `type`.toKotlin() +class PrimitiveType(val name: Identifier) : NotNullType() { + override fun generateCode(builder: CodeBuilder) { + builder.append(name) + } } -class VarArgType(val `type`: Type) : NotNullType { - override fun toKotlin(): String = `type`.toKotlin() +class VarArgType(val `type`: Type) : NotNullType() { + override fun generateCode(builder: CodeBuilder) { + builder.append(`type`) + } } diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/Util.kt b/j2k/src/org/jetbrains/jet/j2k/ast/Util.kt index 739fecfb8a5..f42384e21f6 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ast/Util.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ast/Util.kt @@ -16,67 +16,23 @@ package org.jetbrains.jet.j2k.ast -import java.util.ArrayList - -fun List.toKotlin(separator: String, prefix: String = "", postfix: String = ""): String - = if (isNotEmpty()) map { it.toKotlin() }.makeString(separator, prefix, postfix) else "" +import org.jetbrains.jet.j2k.* fun String.withSuffix(suffix: String): String = if (isEmpty()) "" else this + suffix fun String.withPrefix(prefix: String): String = if (isEmpty()) "" else prefix + this -fun Expression.withPrefix(prefix: String): String = if (isEmpty) "" else prefix + toKotlin() -open class WhiteSpaceSeparatedElementList( - val elements: List, - val minimalWhiteSpace: WhiteSpace, - val ensureSurroundedByWhiteSpace: Boolean = true -) { - val nonEmptyElements = elements.filter { !it.isEmpty } +fun CodeBuilder.appendWithPrefix(element: Element, prefix: String): CodeBuilder = if (!element.isEmpty) this append prefix append element else this +fun CodeBuilder.appendWithSuffix(element: Element, suffix: String): CodeBuilder = if (!element.isEmpty) this append element append suffix else this - fun isEmpty() = nonEmptyElements.all { it is WhiteSpace } - - fun toKotlin(): String { - if (isEmpty()) return "" - return nonEmptyElements.surroundWithWhiteSpaces().insertAndMergeWhiteSpaces().map { it.toKotlin() }.makeString("") - } - - private fun List.surroundWithWhiteSpaces(): List - = if (ensureSurroundedByWhiteSpace) listOf(minimalWhiteSpace) + this + listOf(minimalWhiteSpace) else this - - - // ensure that there is whitespace between non-whitespace elements - // choose maximum among subsequent whitespaces - // all resulting whitespaces are at least minimal whitespace - private fun List.insertAndMergeWhiteSpaces(): List { - var currentWhiteSpace: WhiteSpace? = null - val result = ArrayList() - for (i in 0..lastIndex) { - val element = get(i) - if (element is WhiteSpace) { - if (currentWhiteSpace == null || element > currentWhiteSpace!!) { - currentWhiteSpace = if (element > minimalWhiteSpace) element else minimalWhiteSpace - } - } - else { - if (i != 0) { //do not insert whitespace before first element - result.add(currentWhiteSpace ?: minimalWhiteSpace) - } - result.add(element) - currentWhiteSpace = null - } - } - if (currentWhiteSpace != null) { - result.add(currentWhiteSpace!!) - } - return result - } -} - -fun Expression.operandToKotlin(operand: Expression, parenthesisForSamePrecedence: Boolean = false): String { - val parentPrecedence = precedence() ?: throw IllegalArgumentException("Unknown precendence for $this") - val kotlinCode = operand.toKotlin() - val operandPrecedence = operand.precedence() ?: return kotlinCode - val needParenthesis = parentPrecedence < operandPrecedence || parentPrecedence == operandPrecedence && parenthesisForSamePrecedence - return if (needParenthesis) "($kotlinCode)" else kotlinCode +fun CodeBuilder.appendOperand(expression: Expression, operand: Expression, parenthesisForSamePrecedence: Boolean = false): CodeBuilder { + val parentPrecedence = expression.precedence() ?: throw IllegalArgumentException("Unknown precendence for $this") + val operandPrecedence = operand.precedence() + val needParenthesis = operandPrecedence != null && + (parentPrecedence < operandPrecedence || parentPrecedence == operandPrecedence && parenthesisForSamePrecedence) + if (needParenthesis) append("(") + append(operand) + if (needParenthesis) append(")") + return this } private fun Expression.precedence(): Int? { diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/WhiteSpace.kt b/j2k/src/org/jetbrains/jet/j2k/ast/WhiteSpace.kt deleted file mode 100644 index 4f0e275932a..00000000000 --- a/j2k/src/org/jetbrains/jet/j2k/ast/WhiteSpace.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2010-2013 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.j2k.ast - - -class WhiteSpace(val text: String) : Element { - override fun toKotlin() = text - - override val isEmpty: Boolean - get() = text.isEmpty() - - fun compareTo(other: WhiteSpace): Int { - - fun newLinesCount(w: WhiteSpace) = w.text.count { it == '\n' } - - val lineCountDiff = newLinesCount(this) - newLinesCount(other) - if (lineCountDiff != 0) return lineCountDiff - - fun spacesCount(w: WhiteSpace) = w.text.count { it == ' ' } - - return spacesCount(this) - spacesCount(other) - } - - class object { - val NewLine = WhiteSpace("\n") - val NoSpace = WhiteSpace("") - } -} - - diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/ClassVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/ClassVisitor.kt deleted file mode 100644 index 388707d8c58..00000000000 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/ClassVisitor.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2010-2013 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.j2k.visitors - -import com.intellij.psi.JavaRecursiveElementVisitor -import com.intellij.psi.PsiClass -import java.util.HashSet - -public open class ClassVisitor() : JavaRecursiveElementVisitor() { - private val _classIdentifiers = HashSet() - - public val classIdentifiers: Set - get() = _classIdentifiers - - override fun visitClass(aClass: PsiClass) { - val qName = aClass.getQualifiedName() - if (qName != null) { - _classIdentifiers.add(qName) - } - super.visitClass(aClass) - } -} diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt index 68410680a48..04ae75a7702 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt @@ -20,17 +20,20 @@ import com.intellij.psi.* import org.jetbrains.jet.j2k.* import org.jetbrains.jet.j2k.ast.* -class ElementVisitor(private val converter: Converter, private val typeConverter: TypeConverter) : JavaElementVisitor() { +class ElementVisitor(private val converter: Converter) : JavaElementVisitor() { + private val typeConverter = converter.typeConverter + public var result: Element = Element.Empty protected set override fun visitLocalVariable(variable: PsiLocalVariable) { - result = LocalVariable(Identifier(variable.getName()!!), - converter.convertModifiers(variable), - { typeConverter.convertVariableType(variable) }, - converter.convertExpression(variable.getInitializer(), variable.getType()), - converter.settings.forceLocalVariableImmutability || variable.hasModifierProperty(PsiModifier.FINAL), - converter.settings) + result = LocalVariable(variable.declarationIdentifier(), + converter.convertAnnotations(variable), + converter.convertModifiers(variable), + { typeConverter.convertVariableType(variable) }, + converter.convertExpression(variable.getInitializer(), variable.getType()), + converter.settings.forceLocalVariableImmutability || variable.hasModifierProperty(PsiModifier.FINAL), + converter.settings) } override fun visitExpressionList(list: PsiExpressionList) { @@ -43,11 +46,11 @@ class ElementVisitor(private val converter: Converter, private val typeConverter result = ReferenceElement(Identifier(reference.getReferenceName()!!), types) } else { - var code = Identifier(reference.getReferenceName()!!).toKotlin() + var code = Identifier.toKotlin(reference.getReferenceName()!!) var qualifier = reference.getQualifier() while (qualifier != null) { val p = qualifier as PsiJavaCodeReferenceElement - code = Identifier(p.getReferenceName()!!).toKotlin() + "." + code + code = Identifier.toKotlin(p.getReferenceName()!!) + "." + code qualifier = p.getQualifier() } result = ReferenceElement(Identifier(code), types) @@ -59,19 +62,11 @@ class ElementVisitor(private val converter: Converter, private val typeConverter } override fun visitTypeParameter(classParameter: PsiTypeParameter) { - result = TypeParameter(Identifier(classParameter.getName()!!), - classParameter.getExtendsListTypes().map { typeConverter.convertType(it) }) + result = TypeParameter(classParameter.declarationIdentifier(), + classParameter.getExtendsListTypes().map { typeConverter.convertType(it) }) } override fun visitParameterList(list: PsiParameterList) { result = converter.convertParameterList(list) } - - override fun visitComment(comment: PsiComment) { - result = Comment(comment.getText()!!) - } - - override fun visitWhiteSpace(space: PsiWhiteSpace) { - result = WhiteSpace(space.getText()!!) - } } diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt index c8e06909f38..2a17fa10bbd 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt @@ -36,11 +36,16 @@ import com.intellij.psi.impl.light.LightField import org.jetbrains.jet.lang.resolve.java.JvmAbi class ExpressionVisitor(private val converter: Converter, - private val typeConverter: TypeConverter, private val usageReplacementMap: Map = mapOf()) : JavaElementVisitor() { + private val typeConverter = converter.typeConverter + public var result: Expression = Expression.Empty protected set + public fun reset() { + result = Expression.Empty + } + override fun visitArrayAccessExpression(expression: PsiArrayAccessExpression) { val assignment = PsiTreeUtil.getParentOfType(expression, javaClass()) val lvalue = assignment != null && expression == assignment.getLExpression(); @@ -53,7 +58,8 @@ class ExpressionVisitor(private val converter: Converter, val expressionType = typeConverter.convertType(expression.getType()) assert(expressionType is ArrayType, "Array initializer must have array type") result = createArrayInitializerExpression(expressionType as ArrayType, - converter.convertExpressions(expression.getInitializers())) + converter.convertExpressions(expression.getInitializers()), + needExplicitType = true/*TODO: it's often redundant*/) } override fun visitAssignmentExpression(expression: PsiAssignmentExpression) { @@ -71,7 +77,7 @@ class ExpressionVisitor(private val converter: Converter, val lhs = converter.convertExpression(expression.getLExpression()) val rhs = converter.convertExpression(expression.getRExpression()!!, expression.getLExpression().getType()) if (!secondOp.isEmpty()) { - result = AssignmentExpression(lhs, BinaryExpression(lhs, rhs, secondOp), "=") + result = AssignmentExpression(lhs, BinaryExpression(lhs, rhs, secondOp), " = ") } else { result = AssignmentExpression(lhs, rhs, expression.getOperationSign().getText()!!) @@ -82,7 +88,7 @@ class ExpressionVisitor(private val converter: Converter, val lhs = converter.convertExpression(expression.getLOperand(), expression.getType()) val rhs = converter.convertExpression(expression.getROperand(), expression.getType()) if (expression.getOperationSign().getTokenType() == JavaTokenType.GTGTGT) { - result = MethodCallExpression.build(lhs, "ushr", listOf(rhs)) + result = MethodCallExpression.buildNotNull(lhs, "ushr", listOf(rhs)) } else { result = BinaryExpression(lhs, rhs, getOperatorString(expression.getOperationSign().getTokenType())) @@ -91,7 +97,7 @@ class ExpressionVisitor(private val converter: Converter, override fun visitClassObjectAccessExpression(expression: PsiClassObjectAccessExpression) { val typeElement = converter.convertTypeElement(expression.getOperand()) - result = MethodCallExpression(Identifier("javaClass"), listOf(), listOf(typeElement.`type`.toNotNullType()), false) + result = MethodCallExpression.buildNotNull(null, "javaClass", listOf(), listOf(typeElement.`type`.toNotNullType())) } override fun visitConditionalExpression(expression: PsiConditionalExpression) { @@ -193,16 +199,18 @@ class ExpressionVisitor(private val converter: Converter, if (isTopLevel) { result = if (origin.isExtensionDeclaration()) { val qualifier = converter.convertExpression(arguments.firstOrNull()) - MethodCallExpression(QualifiedExpression(qualifier, Identifier(origin.getName()!!, false)), - convertArguments(expression, isExtension = true), - typeArguments, - isNullable) + MethodCallExpression.build(qualifier, + origin.getName()!!, + convertArguments(expression, isExtension = true), + typeArguments, + isNullable) } else { - MethodCallExpression(Identifier(origin.getName()!!, false), - convertArguments(expression), - typeArguments, - isNullable) + MethodCallExpression.build(null, + origin.getName()!!, + convertArguments(expression), + typeArguments, + isNullable) } return } @@ -231,10 +239,12 @@ class ExpressionVisitor(private val converter: Converter, override fun visitNewExpression(expression: PsiNewExpression) { if (expression.getArrayInitializer() != null) { - result = createNewEmptyArray(expression) + result = converter.convertExpression(expression.getArrayInitializer()) } - else if (expression.getArrayDimensions().size > 0) { - result = createNewEmptyArrayWithoutInitialization(expression) + else if (expression.getArrayDimensions().size > 0 && expression.getType() is PsiArrayType) { + result = ArrayWithoutInitializationExpression( + typeConverter.convertType(expression.getType(), Nullability.NotNull) as ArrayType, + converter.convertExpressions(expression.getArrayDimensions())) } else { result = createNewClassExpression(expression) @@ -243,32 +253,23 @@ class ExpressionVisitor(private val converter: Converter, private fun createNewClassExpression(expression: PsiNewExpression): Expression { val anonymousClass = expression.getAnonymousClass() - val constructor = expression.resolveMethod() val classReference = expression.getClassOrAnonymousClassReference() - val isNotConvertedClass = classReference != null && !converter.getClassIdentifiers().contains(classReference.getQualifiedName()) - val argumentList = expression.getArgumentList() - var arguments = argumentList?.getExpressions() ?: array() - if (constructor == null || constructor.isPrimaryConstructor() || isNotConvertedClass) { - return NewClassExpression(converter.convertElement(classReference), - convertArguments(expression), - converter.convertExpression(expression.getQualifier()), - if (anonymousClass != null) converter.convertAnonymousClass(anonymousClass) else null) + var arguments = expression.getArgumentList()?.getExpressions() ?: array() + + val constructor = expression.resolveMethod() + if (constructor != null && !constructor.isPrimaryConstructor() && converter.conversionScope.contains(constructor)) { + //TODO: handle anonymous class! + // non-primary constructor converted to factory method in class object + val reference = expression.getClassReference() + val typeParameters = if (reference != null) typeConverter.convertTypes(reference.getTypeParameters()) else listOf() + return QualifiedExpression(Identifier(constructor.getName(), false), + MethodCallExpression.buildNotNull(null, "create", converter.convertExpressions(arguments), typeParameters)) } - val reference = expression.getClassReference() - val typeParameters = if (reference != null) typeConverter.convertTypes(reference.getTypeParameters()) else listOf() - return QualifiedExpression(Identifier(constructor.getName(), false), - MethodCallExpression(Identifier("init"), converter.convertExpressions(arguments), typeParameters, false)) - } - - private fun createNewEmptyArrayWithoutInitialization(expression: PsiNewExpression): Expression { - return ArrayWithoutInitializationExpression( - typeConverter.convertType(expression.getType(), Nullability.NotNull), - converter.convertExpressions(expression.getArrayDimensions())) - } - - private fun createNewEmptyArray(expression: PsiNewExpression): Expression { - return converter.convertExpression(expression.getArrayInitializer()) + return NewClassExpression(converter.convertElement(classReference), + convertArguments(expression), + converter.convertExpression(expression.getQualifier()), + if (anonymousClass != null) converter.convertAnonymousClassBody(anonymousClass) else null) } override fun visitParenthesizedExpression(expression: PsiParenthesizedExpression) { @@ -284,7 +285,7 @@ class ExpressionVisitor(private val converter: Converter, val operand = converter.convertExpression(expression.getOperand(), expression.getOperand()!!.getType()) val token = expression.getOperationTokenType() if (token == JavaTokenType.TILDE) { - result = MethodCallExpression.build(operand, "inv", ArrayList()) + result = MethodCallExpression.buildNotNull(operand, "inv") } else if (token == JavaTokenType.EXCL && operand is BinaryExpression && operand.op == "==") { // happens when equals is converted to == result = BinaryExpression(operand.left, operand.right, "!=") @@ -305,7 +306,7 @@ class ExpressionVisitor(private val converter: Converter, val insideSecondaryConstructor = containingConstructor != null && !containingConstructor.isPrimaryConstructor() if (insideSecondaryConstructor && (expression.getReference()?.resolve() as? PsiField)?.getContainingClass() == containingConstructor!!.getContainingClass()) { - identifier = QualifiedExpression(Identifier("__", false), Identifier(referencedName, isNullable)) + identifier = QualifiedExpression(SecondaryConstructor.tempValIdentifier, Identifier(referencedName, isNullable)) } else if (insideSecondaryConstructor && expression.isThisConstructorCall()) { identifier = Identifier("val __ = " + (containingConstructor?.getContainingClass()?.getNameIdentifier()?.getText() ?: "")) @@ -332,12 +333,12 @@ class ExpressionVisitor(private val converter: Converter, if (target is PsiMember && target.hasModifierProperty(PsiModifier.STATIC) && target.getContainingClass() != null - && PsiTreeUtil.getParentOfType(expression, javaClass()) != target.getContainingClass() + && !PsiTreeUtil.isAncestor(target.getContainingClass(), expression, true) && !isStaticallyImported(target, expression)) { var member: PsiMember = target - var code = Identifier(referencedName).toKotlin() + var code = Identifier.toKotlin(referencedName) while (member.getContainingClass() != null) { - code = Identifier(member.getContainingClass()!!.getName()!!).toKotlin() + "." + code + code = Identifier.toKotlin(member.getContainingClass()!!.getName()!!) + "." + code member = member.getContainingClass()!! } result = Identifier(code, false, false) @@ -353,17 +354,17 @@ class ExpressionVisitor(private val converter: Converter, } - result = QualifiedExpression(converter.convertExpression(qualifier), identifier) + result = if (qualifier != null) QualifiedExpression(converter.convertExpression(qualifier), identifier) else identifier } override fun visitSuperExpression(expression: PsiSuperExpression) { - val qualifier = expression.getQualifier() - result = SuperExpression(if (qualifier != null) Identifier(qualifier.getQualifiedName()!!) else Identifier.Empty) + val qualifier = expression.getQualifier()?.getReferenceName() + result = SuperExpression(if (qualifier != null) Identifier(qualifier) else Identifier.Empty) } override fun visitThisExpression(expression: PsiThisExpression) { - val qualifier = expression.getQualifier() - result = ThisExpression(if (qualifier != null) Identifier(qualifier.getQualifiedName()!!) else Identifier.Empty) + val qualifier = expression.getQualifier()?.getReferenceName() + result = ThisExpression(if (qualifier != null) Identifier(qualifier) else Identifier.Empty) } override fun visitTypeCastExpression(expression: PsiTypeCastExpression) { @@ -373,7 +374,7 @@ class ExpressionVisitor(private val converter: Converter, val typeText = castType.getType().getCanonicalText() val typeConversion = PRIMITIVE_TYPE_CONVERSIONS[typeText] if (operandType is PsiPrimitiveType && typeConversion != null) { - result = MethodCallExpression.build(converter.convertExpression(operand), typeConversion) + result = MethodCallExpression.buildNotNull(converter.convertExpression(operand), typeConversion) } else { result = TypeCastExpression(typeConverter.convertType(castType.getType()), diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt index a0e5e85d440..2bcdc76238e 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt @@ -23,18 +23,36 @@ import org.jetbrains.jet.j2k.countWriteAccesses import java.util.ArrayList import org.jetbrains.jet.j2k.hasWriteAccesses import org.jetbrains.jet.j2k.isInSingleLine +import org.jetbrains.jet.j2k.getContainingMethod -class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { +open class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { public var result: Statement = Statement.Empty - private set + protected set + + public fun reset() { + result = Statement.Empty + } override fun visitAssertStatement(statement: PsiAssertStatement) { - result = AssertStatement(converter.convertExpression(statement.getAssertCondition()), - converter.convertExpression(statement.getAssertDescription())) + val descriptionExpr = statement.getAssertDescription() + val condition = converter.convertExpression(statement.getAssertCondition()) + if (descriptionExpr == null) { + result = MethodCallExpression.buildNotNull(null, "assert", listOf(condition)) + } + else { + val description = converter.convertExpression(descriptionExpr) + if (descriptionExpr is PsiLiteralExpression) { + result = MethodCallExpression.buildNotNull(null, "assert", listOf(condition, description)) + } + else { + result = MethodCallExpression.build(null, "assert", listOf(condition), listOf(), false, LambdaExpression(null, Block(listOf(description), LBrace(), RBrace()))) + } + } } override fun visitBlockStatement(statement: PsiBlockStatement) { - result = converter.convertBlock(statement.getCodeBlock()) + val block = converter.convertBlock(statement.getCodeBlock()) + result = MethodCallExpression.build(null, "run", listOf(), listOf(), false, LambdaExpression(null, block)) } override fun visitBreakStatement(statement: PsiBreakStatement) { @@ -56,7 +74,7 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { } override fun visitDeclarationStatement(statement: PsiDeclarationStatement) { - result = DeclarationStatement(converter.convertElements(statement.getDeclaredElements())) + result = DeclarationStatement(statement.getDeclaredElements().map { converter.convertElement(it) }) } override fun visitDoWhileStatement(statement: PsiDoWhileStatement) { @@ -65,7 +83,7 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { converter.convertExpression(condition, condition.getType()) else converter.convertExpression(condition) - result = DoWhileStatement(expression, converter.convertStatement(statement.getBody()), statement.isInSingleLine()) + result = DoWhileStatement(expression, convertStatementOrBlock(statement.getBody()), statement.isInSingleLine()) } override fun visitExpressionStatement(statement: PsiExpressionStatement) { @@ -94,32 +112,58 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { && condition != null && update != null && update.getChildren().size == 1 - && isPlusPlusExpression(update.getChildren().single()) + && update.getChildren().single().isPlusPlusExpression() && (operationTokenType == JavaTokenType.LT || operationTokenType == JavaTokenType.LE) && loopVar != null && loopVar.getNameIdentifier() != null && onceWritableIterator) { val end = converter.convertExpression((condition as PsiBinaryExpression).getROperand()) - val endExpression = if (operationTokenType == JavaTokenType.LT) - BinaryExpression(end, Identifier("1"), "-") - else - end - result = ForeachWithRangeStatement(Identifier(loopVar.getName()!!), + val endExpression = if (operationTokenType == JavaTokenType.LT) BinaryExpression(end, LiteralExpression("1"), "-") else end + result = ForeachWithRangeStatement(loopVar.declarationIdentifier(), converter.convertExpression(loopVar.getInitializer()), endExpression, - converter.convertStatement(body), + convertStatementOrBlock(body), statement.isInSingleLine()) } else { - var forStatements = ArrayList() - forStatements.add(converter.convertStatement(initialization)) - val bodyAndUpdate = listOf(converter.convertStatement(body), - Block(listOf(converter.convertStatement(update)))) - forStatements.add(WhileStatement( - if (condition == null) LiteralExpression("true") else converter.convertExpression(condition), - Block(bodyAndUpdate), - statement.isInSingleLine())) - result = Block(forStatements) + val initializationConverted = converter.convertStatement(initialization) + val updateConverted = converter.convertStatement(update) + + val whileBody = if (updateConverted.isEmpty) { + convertStatementOrBlock(body) + } + else if (body is PsiBlockStatement) { + val nameConflict = initialization is PsiDeclarationStatement && initialization.getDeclaredElements().any { loopVar -> + loopVar is PsiNamedElement && body.getCodeBlock().getStatements().any { statement -> + statement is PsiDeclarationStatement && statement.getDeclaredElements().any { + it is PsiNamedElement && it.getName() == loopVar.getName() + } + } + } + + if (nameConflict) { + Block(listOf(converter.convertStatement(body), updateConverted), LBrace(), RBrace(), true) + } + else { + val block = converter.convertBlock(body.getCodeBlock(), true) + Block(block.statements + listOf(updateConverted), block.lBrace, block.rBrace, true).assignPrototypesFrom(block) + } + } + else { + Block(listOf(converter.convertStatement(body), updateConverted), LBrace(), RBrace(), true) + } + val whileStatement = WhileStatement( + if (condition != null) converter.convertExpression(condition) else LiteralExpression("true"), + whileBody, + statement.isInSingleLine()) + + if (initializationConverted.isEmpty) { + result = whileStatement + } + else { + val block = Block(listOf(initializationConverted, whileStatement), LBrace(), RBrace()) + result = MethodCallExpression.build(null, "run", listOf(), listOf(), false, LambdaExpression(null, block)) + } } } @@ -133,7 +177,7 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { } result = ForeachStatement(converter.convertParameter(statement.getIterationParameter()), iterator, - converter.convertStatement(statement.getBody()), + convertStatementOrBlock(statement.getBody()), statement.isInSingleLine()) } @@ -141,8 +185,8 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { val condition = statement.getCondition() val expression = converter.convertExpression(condition, PsiType.BOOLEAN) result = IfStatement(expression, - converter.convertStatement(statement.getThenBranch()), - converter.convertStatement(statement.getElseBranch()), + convertStatementOrBlock(statement.getThenBranch()), + convertStatementOrBlock(statement.getElseBranch()), statement.isInSingleLine()) } @@ -217,16 +261,77 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { result = ThrowStatement(converter.convertExpression(statement.getException())) } - override fun visitTryStatement(statement: PsiTryStatement) { - val catches = ArrayList() - val catchBlocks = statement.getCatchBlocks() - val catchBlockParameters = statement.getCatchBlockParameters() - for (i in 0..catchBlocks.size - 1) { - catches.add(CatchStatement(converter.convertParameter(catchBlockParameters[i], Nullability.NotNull), - converter.convertBlock(catchBlocks[i]))) + override fun visitTryStatement(tryStatement: PsiTryStatement) { + val tryBlock = tryStatement.getTryBlock() + val catchesConverted = run { + val catchBlocks = tryStatement.getCatchBlocks() + val catchBlockParameters = tryStatement.getCatchBlockParameters() + catchBlocks.indices.map { + CatchStatement(converter.convertParameter(catchBlockParameters[it], Nullability.NotNull), + converter.convertBlock(catchBlocks[it])) + } } - result = TryStatement(converter.convertBlock(statement.getTryBlock()), - catches, converter.convertBlock(statement.getFinallyBlock())) + val finallyConverted = converter.convertBlock(tryStatement.getFinallyBlock()) + + val resourceList = tryStatement.getResourceList() + if (resourceList != null) { + val variables = resourceList.getResourceVariables() + if (variables.isNotEmpty()) { + result = convertTryWithResources(tryBlock, variables, catchesConverted, finallyConverted) + return + } + } + + result = TryStatement(converter.convertBlock(tryBlock), catchesConverted, finallyConverted) + } + + private fun convertTryWithResources(tryBlock: PsiCodeBlock?, resourceVariables: List, catchesConverted: List, finallyConverted: Block): Statement { + var wrapResultStatement: (Expression) -> Statement = { it } + var converterForBody = converter + + val returns = collectReturns(tryBlock) + //TODO: support other returns when non-local returns supported by Kotlin + if (returns.size == 1 && returns.single() == tryBlock!!.getStatements().last()) { + wrapResultStatement = { ReturnStatement(it) } + converterForBody = converter.withStatementVisitor { object : StatementVisitor(it) { + override fun visitReturnStatement(statement: PsiReturnStatement) { + if (statement == returns.single()) { + result = converter.convertExpression(statement.getReturnValue(), tryBlock!!.getContainingMethod()?.getReturnType()) + } + else { + super.visitReturnStatement(statement) + } + } + }} + } + + var block = converterForBody.convertBlock(tryBlock) + var expression: Expression = Expression.Empty + for (variable in resourceVariables.reverse()) { + val lambda = LambdaExpression(Identifier.toKotlin(variable.getName()!!), block) + expression = MethodCallExpression.build(converter.convertExpression(variable.getInitializer()), "use", listOf(), listOf(), false, lambda) + block = Block(listOf(expression), LBrace(), RBrace()) + } + + if (catchesConverted.isEmpty() && finallyConverted.isEmpty) { + return wrapResultStatement(expression) + } + + return TryStatement(Block(listOf(wrapResultStatement(expression)), LBrace(), RBrace(), true), catchesConverted, finallyConverted) + } + + private fun collectReturns(block: PsiCodeBlock?): Collection { + val returns = ArrayList() + block?.accept(object: JavaRecursiveElementVisitor() { + override fun visitReturnStatement(statement: PsiReturnStatement) { + returns.add(statement) + } + + override fun visitMethod(method: PsiMethod) { + // do not go inside any other method (e.g. in anonymous class) + } + }) + return returns } override fun visitWhileStatement(statement: PsiWhileStatement) { @@ -235,16 +340,16 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { converter.convertExpression(condition, condition!!.getType()) else converter.convertExpression(condition) - result = WhileStatement(expression, converter.convertStatement(statement.getBody()), statement.isInSingleLine()) + result = WhileStatement(expression, convertStatementOrBlock(statement.getBody()), statement.isInSingleLine()) } override fun visitReturnStatement(statement: PsiReturnStatement) { val returnValue = statement.getReturnValue() val methodReturnType = converter.methodReturnType - val expression = (if (returnValue != null && methodReturnType != null) + val expression = if (returnValue != null && methodReturnType != null) converter.convertExpression(returnValue, methodReturnType) else - converter.convertExpression(returnValue)) + converter.convertExpression(returnValue) result = ReturnStatement(expression) } @@ -252,9 +357,9 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { result = Statement.Empty } - private fun isPlusPlusExpression(psiElement: PsiElement): Boolean { - return (psiElement is PsiPostfixExpression && psiElement.getOperationTokenType() == JavaTokenType.PLUSPLUS) || - (psiElement is PsiPrefixExpression && psiElement.getOperationTokenType() == JavaTokenType.PLUSPLUS) + private fun PsiElement.isPlusPlusExpression(): Boolean { + return (this is PsiPostfixExpression && this.getOperationTokenType() == JavaTokenType.PLUSPLUS) || + (this is PsiPrefixExpression && this.getOperationTokenType() == JavaTokenType.PLUSPLUS) } private fun containsBreak(slice: List) = slice.any { it is PsiBreakStatement } @@ -299,4 +404,11 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { return cases } + + private fun convertStatementOrBlock(statement: PsiStatement?): Statement { + return if (statement is PsiBlockStatement) + converter.convertBlock(statement.getCodeBlock()) + else + converter.convertStatement(statement) + } } diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/TypeVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/TypeVisitor.kt index db3ce2944fc..718835039df 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/TypeVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/TypeVisitor.kt @@ -27,7 +27,7 @@ import org.jetbrains.jet.j2k.TypeConverter private val PRIMITIVE_TYPES_NAMES = JvmPrimitiveType.values().map { it.getName() } -open class TypeVisitor(private val converter: TypeConverter) : PsiTypeVisitor() { +class TypeVisitor(private val converter: TypeConverter, private val importNames: Set, private val classesToImport: MutableSet) : PsiTypeVisitor() { override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type { val name = primitiveType.getCanonicalText() return if (name == "void") { @@ -36,6 +36,9 @@ open class TypeVisitor(private val converter: TypeConverter) : PsiTypeVisitor 0) { val starParamList = ArrayList() if (resolvedClassTypeParams.size() == 1) { - if ((resolvedClassTypeParams.single() as ClassType).`type`.name == "Any") { + if ((resolvedClassTypeParams.single() as ClassType).name.name == "Any") { starParamList.add(StarProjectionType()) return ClassType(identifier, starParamList, Nullability.Default, converter.settings) } @@ -71,37 +74,53 @@ open class TypeVisitor(private val converter: TypeConverter) : PsiTypeVisitor return Identifier(CommonClassNames.JAVA_LANG_ITERABLE) - CommonClassNames.JAVA_UTIL_ITERATOR -> return Identifier(CommonClassNames.JAVA_UTIL_ITERATOR) - CommonClassNames.JAVA_UTIL_LIST -> return Identifier("MutableList") + val javaClassName = psiClass.getQualifiedName() + val kotlinClassName = toKotlinTypesMap[javaClassName] + if (kotlinClassName != null) { + val kotlinShortName = getShortName(kotlinClassName) + if (kotlinShortName == getShortName(javaClassName!!) && importNames.contains(getPackageName(javaClassName) + ".*")) { + classesToImport.add(kotlinClassName) + } + return Identifier(kotlinShortName) } } - val classTypeName = createQualifiedName(classType) - if (classTypeName.isEmpty()) { - return Identifier(getClassTypeName(classType)) + if (classType is PsiClassReferenceType) { + val reference = classType.getReference() + if (reference.isQualified()) { + var result = Identifier.toKotlin(reference.getReferenceName()!!) + var qualifier = reference.getQualifier() + while (qualifier != null) { + val codeRefElement = qualifier as PsiJavaCodeReferenceElement + result = Identifier.toKotlin(codeRefElement.getReferenceName()!!) + "." + result + qualifier = codeRefElement.getQualifier() + } + return Identifier(result) + } } - return Identifier(classTypeName) + return Identifier(classType.getClassName() ?: "") } + private fun getPackageName(className: String): String = className.substring(0, className.lastIndexOf('.')) + private fun getShortName(className: String): String = className.substring(className.lastIndexOf('.') + 1) + private fun createRawTypesForResolvedReference(classType: PsiClassType): List { val typeParams = LinkedList() if (classType is PsiClassReferenceType) { - val reference = classType.getReference() - val resolve = reference.resolve() + val resolve = classType.getReference().resolve() if (resolve is PsiClass) { for (typeParam in resolve.getTypeParameters()) { val superTypes = typeParam.getSuperTypes() - val boundType = if (superTypes.size > 0) - ClassType(Identifier(getClassTypeName(superTypes[0])), + val boundType = if (superTypes.size > 0) { + ClassType(constructClassTypeIdentifier(superTypes[0]), converter.convertTypes(superTypes[0].getParameters()), Nullability.Default, converter.settings) - else + } + else { StarProjectionType() + } typeParams.add(boundType) } } @@ -122,38 +141,23 @@ open class TypeVisitor(private val converter: TypeConverter) : PsiTypeVisitor "Any" - CommonClassNames.JAVA_LANG_BYTE -> "Byte" - CommonClassNames.JAVA_LANG_CHARACTER -> "Char" - CommonClassNames.JAVA_LANG_DOUBLE -> "Double" - CommonClassNames.JAVA_LANG_FLOAT -> "Float" - CommonClassNames.JAVA_LANG_INTEGER -> "Int" - CommonClassNames.JAVA_LANG_LONG -> "Long" - CommonClassNames.JAVA_LANG_SHORT -> "Short" - CommonClassNames.JAVA_LANG_BOOLEAN -> "Boolean" - - else -> classType.getClassName() ?: classType.getCanonicalText() - } + class object { + private val toKotlinTypesMap: Map = mapOf( + CommonClassNames.JAVA_LANG_OBJECT to "kotlin.Any", + CommonClassNames.JAVA_LANG_BYTE to "kotlin.Byte", + CommonClassNames.JAVA_LANG_CHARACTER to "kotlin.Char", + CommonClassNames.JAVA_LANG_DOUBLE to "kotlin.Double", + CommonClassNames.JAVA_LANG_FLOAT to "kotlin.Float", + CommonClassNames.JAVA_LANG_INTEGER to "kotlin.Int", + CommonClassNames.JAVA_LANG_LONG to "kotlin.Long", + CommonClassNames.JAVA_LANG_SHORT to "kotlin.Short", + CommonClassNames.JAVA_LANG_BOOLEAN to "kotlin.Boolean", + CommonClassNames.JAVA_LANG_ITERABLE to "kotlin.Iterable", + CommonClassNames.JAVA_UTIL_ITERATOR to "kotlin.Iterator", + CommonClassNames.JAVA_UTIL_LIST to "kotlin.List", + CommonClassNames.JAVA_UTIL_COLLECTION to "kotlin.Collection", + CommonClassNames.JAVA_UTIL_SET to "kotlin.Set", + CommonClassNames.JAVA_UTIL_MAP to "kotlin.Map" + ) } } diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/AbstractJavaToKotlinConverterTest.kt b/j2k/tests/test/org/jetbrains/jet/j2k/test/AbstractJavaToKotlinConverterTest.kt index b988bff7328..a5517f649db 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/AbstractJavaToKotlinConverterTest.kt +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/AbstractJavaToKotlinConverterTest.kt @@ -33,6 +33,8 @@ import org.jetbrains.jet.JetTestUtils import com.intellij.openapi.project.Project import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.application.ApplicationManager +import org.jetbrains.jet.test.util.trimIndent +import org.jetbrains.jet.j2k.FilesConversionScope abstract class AbstractJavaToKotlinConverterTest() : LightIdeaTestCase() { val testHeaderPattern = Pattern.compile("//(element|expression|statement|method|class|file|comp)\n") @@ -40,11 +42,17 @@ abstract class AbstractJavaToKotlinConverterTest() : LightIdeaTestCase() { override fun setUp() { super.setUp() + fun addFile(fileName: String, packageName: String) { + val code = FileUtil.loadFile(File("j2k/tests/testData/$fileName"), true) + val root = LightPlatformTestCase.getSourceRoot()!! + val dir = root.findChild(packageName) ?: root.createChildDirectory(null, packageName) + val file = dir.createChildData(null, fileName)!! + file.getOutputStream(null)!!.writer().use { it.write(code) } + } + ApplicationManager.getApplication()!!.runWriteAction{ - val kotlinApiFileName = "KotlinApi.kt" - val kotlinCode = FileUtil.loadFile(File("j2k/tests/testData/$kotlinApiFileName"), true) - val kotlinFile = LightPlatformTestCase.getSourceRoot()!!.createChildData(null, kotlinApiFileName)!! - kotlinFile.getOutputStream(null)!!.writer().use { it.write(kotlinCode) } + addFile("KotlinApi.kt", "kotlinApi") + addFile("JavaApi.java", "javaApi") } } @@ -70,19 +78,19 @@ abstract class AbstractJavaToKotlinConverterTest() : LightIdeaTestCase() { "forceNotNullTypes" -> settings.forceNotNullTypes = parseBoolean(value) "forceLocalVariableImmutability" -> settings.forceLocalVariableImmutability = parseBoolean(value) "specifyLocalVariableTypeByDefault" -> settings.specifyLocalVariableTypeByDefault = parseBoolean(value) + "specifyFieldTypeByDefault" -> settings.specifyFieldTypeByDefault = parseBoolean(value) "openByDefault" -> settings.openByDefault = parseBoolean(value) else -> throw IllegalArgumentException("Unknown option: $name") } } - val converter = Converter(project, settings) val rawConverted = when (prefix) { - "element" -> elementToKotlin(converter, javaCode) - "expression" -> expressionToKotlin(converter, javaCode) - "statement" -> statementToKotlin(converter, javaCode) - "method" -> methodToKotlin(converter, javaCode) - "class" -> fileToKotlin(converter, javaCode) - "file" -> fileToKotlin(converter, javaCode) + "element" -> elementToKotlin(javaCode, settings, project) + "expression" -> expressionToKotlin(javaCode, settings, project) + "statement" -> statementToKotlin(javaCode, settings, project) + "method" -> methodToKotlin(javaCode, settings, project) + "class" -> fileToKotlin(javaCode, settings, project) + "file" -> fileToKotlin(javaCode, settings, project) else -> throw IllegalStateException("Specify what is it: file, class, method, statement or expression " + "using the first line of test data file") } @@ -114,42 +122,32 @@ abstract class AbstractJavaToKotlinConverterTest() : LightIdeaTestCase() { reformattedText } - private fun elementToKotlin(converter: Converter, text: String): String { - val fileWithText = JavaToKotlinTranslator.createFile(converter.project, text)!! + private fun elementToKotlin(text: String, settings: ConverterSettings, project: Project): String { + val fileWithText = JavaToKotlinTranslator.createFile(project, text) + val converter = Converter.create(project, settings, FilesConversionScope(listOf(fileWithText))) val element = fileWithText.getFirstChild()!! return converter.elementToKotlin(element) } - private fun fileToKotlin(converter: Converter, text: String): String { - return generateKotlinCode(converter, JavaToKotlinTranslator.createFile(converter.project, text)) + private fun fileToKotlin(text: String, settings: ConverterSettings, project: Project): String { + val file = JavaToKotlinTranslator.createFile(project, text) + val converter = Converter.create(project, settings, FilesConversionScope(listOf(file))) + return converter.elementToKotlin(file) } - private fun methodToKotlin(converter: Converter, text: String?): String { - var result = fileToKotlin(converter, "final class C {" + text + "}").replaceAll("class C\\(\\) \\{", "") - result = result.substring(0, (result.lastIndexOf("}"))).trim() - return result + private fun methodToKotlin(text: String, settings: ConverterSettings, project: Project): String { + val result = fileToKotlin("final class C {" + text + "}", settings, project).replaceAll("class C\\(\\) \\{", "") + return result.substring(0, (result.lastIndexOf("}"))).trim() } - private fun statementToKotlin(converter: Converter, text: String?): String { - var result = methodToKotlin(converter, "void main() {" + text + "}") - val pos = result.lastIndexOf("}") - result = result.substring(0, pos).replaceFirst("fun main\\(\\) \\{", "").trim() - return result + private fun statementToKotlin(text: String, settings: ConverterSettings, project: Project): String { + val result = methodToKotlin("void main() {" + text + "}", settings, project) + return result.substring(0, result.lastIndexOf("}")).replaceFirst("fun main\\(\\) \\{", "").trim() } - private fun expressionToKotlin(converter: Converter, code: String?): String { - var result = statementToKotlin(converter, "final Object o =" + code + "}") - result = result.replaceFirst("val o : Any\\? =", "").replaceFirst("val o : Any = ", "").replaceFirst("val o = ", "").trim() - return result - } - - private fun generateKotlinCode(converter: Converter, file: PsiFile?): String { - if (file is PsiJavaFile) { - JavaToKotlinTranslator.setClassIdentifiers(converter, file) - return converter.elementToKotlin(file) - } - - return "" + private fun expressionToKotlin(code: String, settings: ConverterSettings, project: Project): String { + val result = statementToKotlin("final Object o =" + code + "}", settings, project) + return result.replaceFirst("val o:Any\\? = ", "").replaceFirst("val o:Any = ", "").replaceFirst("val o = ", "").trim() } override fun getProjectJDK(): Sdk? { @@ -165,32 +163,4 @@ abstract class AbstractJavaToKotlinConverterTest() : LightIdeaTestCase() { val lastNewLine = lastIndexOf('\n') return if (lastNewLine == -1) "" else substring(0, lastNewLine) } - - private fun String.trimIndent(): String { - val lines = split('\n') - - val firstNonEmpty = lines.firstOrNull { !it.trim().isEmpty() } - if (firstNonEmpty == null) { - return this - } - - val trimmedPrefix = firstNonEmpty.takeWhile { ch -> ch.isWhitespace() } - if (trimmedPrefix.isEmpty()) { - return this - } - - return lines.map { line -> - if (line.trim().isEmpty()) { - "" - } - else { - if (!line.startsWith(trimmedPrefix)) { - throw IllegalArgumentException( - """Invalid line "$line", ${trimmedPrefix.size} whitespace character are expected""") - } - - line.substring(trimmedPrefix.length) - } - }.makeString(separator = "\n") - } } \ No newline at end of file diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java index ad6d08d33fd..db113760629 100644 --- a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java +++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java @@ -31,7 +31,7 @@ import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("j2k/tests/testData/ast") -@InnerTestClasses({JavaToKotlinConverterTestGenerated.Annotations.class, JavaToKotlinConverterTestGenerated.AnonymousBlock.class, JavaToKotlinConverterTestGenerated.ArrayAccessExpression.class, JavaToKotlinConverterTestGenerated.ArrayInitializerExpression.class, JavaToKotlinConverterTestGenerated.ArrayType.class, JavaToKotlinConverterTestGenerated.AssertStatement.class, JavaToKotlinConverterTestGenerated.AssignmentExpression.class, JavaToKotlinConverterTestGenerated.BinaryExpression.class, JavaToKotlinConverterTestGenerated.BoxedType.class, JavaToKotlinConverterTestGenerated.BreakStatement.class, JavaToKotlinConverterTestGenerated.CallChainExpression.class, JavaToKotlinConverterTestGenerated.Class.class, JavaToKotlinConverterTestGenerated.ClassExpression.class, JavaToKotlinConverterTestGenerated.ConditionalExpression.class, JavaToKotlinConverterTestGenerated.Constructors.class, JavaToKotlinConverterTestGenerated.ContinueStatement.class, JavaToKotlinConverterTestGenerated.DeclarationStatement.class, JavaToKotlinConverterTestGenerated.DoWhileStatement.class, JavaToKotlinConverterTestGenerated.Enum.class, JavaToKotlinConverterTestGenerated.Equals.class, JavaToKotlinConverterTestGenerated.Field.class, JavaToKotlinConverterTestGenerated.For.class, JavaToKotlinConverterTestGenerated.ForeachStatement.class, JavaToKotlinConverterTestGenerated.Formatting.class, JavaToKotlinConverterTestGenerated.Function.class, JavaToKotlinConverterTestGenerated.Identifier.class, JavaToKotlinConverterTestGenerated.IfStatement.class, JavaToKotlinConverterTestGenerated.ImportStatement.class, JavaToKotlinConverterTestGenerated.InProjectionType.class, JavaToKotlinConverterTestGenerated.Inheritance.class, JavaToKotlinConverterTestGenerated.IsOperator.class, JavaToKotlinConverterTestGenerated.Issues.class, JavaToKotlinConverterTestGenerated.KotlinApiAccess.class, JavaToKotlinConverterTestGenerated.KotlinExclusion.class, JavaToKotlinConverterTestGenerated.LabelStatement.class, JavaToKotlinConverterTestGenerated.List.class, JavaToKotlinConverterTestGenerated.LiteralExpression.class, JavaToKotlinConverterTestGenerated.LocalVariable.class, JavaToKotlinConverterTestGenerated.MethodCallExpression.class, JavaToKotlinConverterTestGenerated.Misc.class, JavaToKotlinConverterTestGenerated.NewClassExpression.class, JavaToKotlinConverterTestGenerated.Nullability.class, JavaToKotlinConverterTestGenerated.ObjectLiteral.class, JavaToKotlinConverterTestGenerated.OutProjectionType.class, JavaToKotlinConverterTestGenerated.PackageStatement.class, JavaToKotlinConverterTestGenerated.ParenthesizedExpression.class, JavaToKotlinConverterTestGenerated.PolyadicExpression.class, JavaToKotlinConverterTestGenerated.PostfixOperator.class, JavaToKotlinConverterTestGenerated.PrefixOperator.class, JavaToKotlinConverterTestGenerated.RawGenerics.class, JavaToKotlinConverterTestGenerated.ReturnStatement.class, JavaToKotlinConverterTestGenerated.Settings.class, JavaToKotlinConverterTestGenerated.StarProjectionType.class, JavaToKotlinConverterTestGenerated.SuperExpression.class, JavaToKotlinConverterTestGenerated.Switch.class, JavaToKotlinConverterTestGenerated.SynchronizedStatement.class, JavaToKotlinConverterTestGenerated.ThisExpression.class, JavaToKotlinConverterTestGenerated.ThrowStatement.class, JavaToKotlinConverterTestGenerated.Trait.class, JavaToKotlinConverterTestGenerated.TryStatement.class, JavaToKotlinConverterTestGenerated.TypeCastExpression.class, JavaToKotlinConverterTestGenerated.TypeParameters.class, JavaToKotlinConverterTestGenerated.VarArg.class, JavaToKotlinConverterTestGenerated.WhileStatement.class}) +@InnerTestClasses({JavaToKotlinConverterTestGenerated.Annotations.class, JavaToKotlinConverterTestGenerated.AnonymousBlock.class, JavaToKotlinConverterTestGenerated.ArrayAccessExpression.class, JavaToKotlinConverterTestGenerated.ArrayInitializerExpression.class, JavaToKotlinConverterTestGenerated.ArrayType.class, JavaToKotlinConverterTestGenerated.AssertStatement.class, JavaToKotlinConverterTestGenerated.AssignmentExpression.class, JavaToKotlinConverterTestGenerated.BinaryExpression.class, JavaToKotlinConverterTestGenerated.Blocks.class, JavaToKotlinConverterTestGenerated.BoxedType.class, JavaToKotlinConverterTestGenerated.BreakStatement.class, JavaToKotlinConverterTestGenerated.CallChainExpression.class, JavaToKotlinConverterTestGenerated.Class.class, JavaToKotlinConverterTestGenerated.ClassExpression.class, JavaToKotlinConverterTestGenerated.Comments.class, JavaToKotlinConverterTestGenerated.ConditionalExpression.class, JavaToKotlinConverterTestGenerated.Constructors.class, JavaToKotlinConverterTestGenerated.ContinueStatement.class, JavaToKotlinConverterTestGenerated.DeclarationStatement.class, JavaToKotlinConverterTestGenerated.DoWhileStatement.class, JavaToKotlinConverterTestGenerated.Enum.class, JavaToKotlinConverterTestGenerated.Equals.class, JavaToKotlinConverterTestGenerated.Field.class, JavaToKotlinConverterTestGenerated.For.class, JavaToKotlinConverterTestGenerated.ForeachStatement.class, JavaToKotlinConverterTestGenerated.Formatting.class, JavaToKotlinConverterTestGenerated.Function.class, JavaToKotlinConverterTestGenerated.Identifier.class, JavaToKotlinConverterTestGenerated.IfStatement.class, JavaToKotlinConverterTestGenerated.ImportStatement.class, JavaToKotlinConverterTestGenerated.InProjectionType.class, JavaToKotlinConverterTestGenerated.Inheritance.class, JavaToKotlinConverterTestGenerated.IsOperator.class, JavaToKotlinConverterTestGenerated.Issues.class, JavaToKotlinConverterTestGenerated.KotlinApiAccess.class, JavaToKotlinConverterTestGenerated.LabelStatement.class, JavaToKotlinConverterTestGenerated.List.class, JavaToKotlinConverterTestGenerated.LiteralExpression.class, JavaToKotlinConverterTestGenerated.LocalVariable.class, JavaToKotlinConverterTestGenerated.MethodCallExpression.class, JavaToKotlinConverterTestGenerated.Misc.class, JavaToKotlinConverterTestGenerated.NewClassExpression.class, JavaToKotlinConverterTestGenerated.Nullability.class, JavaToKotlinConverterTestGenerated.ObjectLiteral.class, JavaToKotlinConverterTestGenerated.OutProjectionType.class, JavaToKotlinConverterTestGenerated.PackageStatement.class, JavaToKotlinConverterTestGenerated.ParenthesizedExpression.class, JavaToKotlinConverterTestGenerated.PolyadicExpression.class, JavaToKotlinConverterTestGenerated.PostfixOperator.class, JavaToKotlinConverterTestGenerated.PrefixOperator.class, JavaToKotlinConverterTestGenerated.RawGenerics.class, JavaToKotlinConverterTestGenerated.ReturnStatement.class, JavaToKotlinConverterTestGenerated.Settings.class, JavaToKotlinConverterTestGenerated.StarProjectionType.class, JavaToKotlinConverterTestGenerated.StaticMembers.class, JavaToKotlinConverterTestGenerated.SuperExpression.class, JavaToKotlinConverterTestGenerated.Switch.class, JavaToKotlinConverterTestGenerated.SynchronizedStatement.class, JavaToKotlinConverterTestGenerated.ThisExpression.class, JavaToKotlinConverterTestGenerated.ThrowStatement.class, JavaToKotlinConverterTestGenerated.ToKotlinClasses.class, JavaToKotlinConverterTestGenerated.Trait.class, JavaToKotlinConverterTestGenerated.TryStatement.class, JavaToKotlinConverterTestGenerated.TryWithResource.class, JavaToKotlinConverterTestGenerated.TypeCastExpression.class, JavaToKotlinConverterTestGenerated.TypeParameters.class, JavaToKotlinConverterTestGenerated.VarArg.class, JavaToKotlinConverterTestGenerated.WhileStatement.class}) public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConverterTest { public void testAllFilesPresentInAst() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast"), Pattern.compile("^(.+)\\.java$"), true); @@ -43,6 +43,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/annotations"), Pattern.compile("^(.+)\\.java$"), true); } + @TestMetadata("annotationUsages.java") + public void testAnnotationUsages() throws Exception { + doTest("j2k/tests/testData/ast/annotations/annotationUsages.java"); + } + @TestMetadata("jetbrainsNotNull.java") public void testJetbrainsNotNull() throws Exception { doTest("j2k/tests/testData/ast/annotations/jetbrainsNotNull.java"); @@ -248,6 +253,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/assertStatement/withStringDetail.java"); } + @TestMetadata("withStringDetail2.java") + public void testWithStringDetail2() throws Exception { + doTest("j2k/tests/testData/ast/assertStatement/withStringDetail2.java"); + } + } @TestMetadata("j2k/tests/testData/ast/assignmentExpression") @@ -431,6 +441,19 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv } + @TestMetadata("j2k/tests/testData/ast/blocks") + public static class Blocks extends AbstractJavaToKotlinConverterTest { + public void testAllFilesPresentInBlocks() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/blocks"), Pattern.compile("^(.+)\\.java$"), true); + } + + @TestMetadata("Blocks.java") + public void testBlocks() throws Exception { + doTest("j2k/tests/testData/ast/blocks/Blocks.java"); + } + + } + @TestMetadata("j2k/tests/testData/ast/boxedType") public static class BoxedType extends AbstractJavaToKotlinConverterTest { public void testAllFilesPresentInBoxedType() throws Exception { @@ -616,11 +639,26 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/class/genericClass.java"); } + @TestMetadata("innerClassInInterface.java") + public void testInnerClassInInterface() throws Exception { + doTest("j2k/tests/testData/ast/class/innerClassInInterface.java"); + } + @TestMetadata("innerEmptyClass.java") public void testInnerEmptyClass() throws Exception { doTest("j2k/tests/testData/ast/class/innerEmptyClass.java"); } + @TestMetadata("innerEnum.java") + public void testInnerEnum() throws Exception { + doTest("j2k/tests/testData/ast/class/innerEnum.java"); + } + + @TestMetadata("innerInterface.java") + public void testInnerInterface() throws Exception { + doTest("j2k/tests/testData/ast/class/innerInterface.java"); + } + @TestMetadata("innerStaticClass.java") public void testInnerStaticClass() throws Exception { doTest("j2k/tests/testData/ast/class/innerStaticClass.java"); @@ -706,6 +744,34 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv } + @TestMetadata("j2k/tests/testData/ast/comments") + public static class Comments extends AbstractJavaToKotlinConverterTest { + public void testAllFilesPresentInComments() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/comments"), Pattern.compile("^(.+)\\.java$"), true); + } + + @TestMetadata("comments.java") + public void testComments() throws Exception { + doTest("j2k/tests/testData/ast/comments/comments.java"); + } + + @TestMetadata("comments2.java") + public void testComments2() throws Exception { + doTest("j2k/tests/testData/ast/comments/comments2.java"); + } + + @TestMetadata("fieldWithEndOfLineComment.java") + public void testFieldWithEndOfLineComment() throws Exception { + doTest("j2k/tests/testData/ast/comments/fieldWithEndOfLineComment.java"); + } + + @TestMetadata("fieldsInitializedFromParams.java") + public void testFieldsInitializedFromParams() throws Exception { + doTest("j2k/tests/testData/ast/comments/fieldsInitializedFromParams.java"); + } + + } + @TestMetadata("j2k/tests/testData/ast/conditionalExpression") public static class ConditionalExpression extends AbstractJavaToKotlinConverterTest { public void testAllFilesPresentInConditionalExpression() throws Exception { @@ -1028,6 +1094,16 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/field/publicField.java"); } + @TestMetadata("specifyType.java") + public void testSpecifyType() throws Exception { + doTest("j2k/tests/testData/ast/field/specifyType.java"); + } + + @TestMetadata("valOrVar.java") + public void testValOrVar() throws Exception { + doTest("j2k/tests/testData/ast/field/valOrVar.java"); + } + @TestMetadata("valWithInit.java") public void testValWithInit() throws Exception { doTest("j2k/tests/testData/ast/field/valWithInit.java"); @@ -1056,6 +1132,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/for/commonCaseForTest.java"); } + @TestMetadata("forRangeWithBlock.java") + public void testForRangeWithBlock() throws Exception { + doTest("j2k/tests/testData/ast/for/forRangeWithBlock.java"); + } + @TestMetadata("forRangeWithLE.java") public void testForRangeWithLE() throws Exception { doTest("j2k/tests/testData/ast/for/forRangeWithLE.java"); @@ -1106,6 +1187,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/for/forWithReturn.java"); } + @TestMetadata("infiniteFor.java") + public void testInfiniteFor() throws Exception { + doTest("j2k/tests/testData/ast/for/infiniteFor.java"); + } + } @TestMetadata("j2k/tests/testData/ast/foreachStatement") @@ -1255,6 +1341,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/function/overrideObject2.java"); } + @TestMetadata("overrideObject3.java") + public void testOverrideObject3() throws Exception { + doTest("j2k/tests/testData/ast/function/overrideObject3.java"); + } + @TestMetadata("ownGenericParam.java") public void testOwnGenericParam() throws Exception { doTest("j2k/tests/testData/ast/function/ownGenericParam.java"); @@ -1280,6 +1371,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/function/public.java"); } + @TestMetadata("throws.java") + public void testThrows() throws Exception { + doTest("j2k/tests/testData/ast/function/throws.java"); + } + @TestMetadata("varVararg.java") public void testVarVararg() throws Exception { doTest("j2k/tests/testData/ast/function/varVararg.java"); @@ -1456,6 +1552,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/issues/comments.java"); } + @TestMetadata("doNotQualifyStatic.java") + public void testDoNotQualifyStatic() throws Exception { + doTest("j2k/tests/testData/ast/issues/doNotQualifyStatic.java"); + } + @TestMetadata("kt-1016.java") public void testKt_1016() throws Exception { doTest("j2k/tests/testData/ast/issues/kt-1016.java"); @@ -1596,6 +1697,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/issues/qualifyStatic.java"); } + @TestMetadata("spaceBeforeAssignment.java") + public void testSpaceBeforeAssignment() throws Exception { + doTest("j2k/tests/testData/ast/issues/spaceBeforeAssignment.java"); + } + } @TestMetadata("j2k/tests/testData/ast/kotlinApiAccess") @@ -1666,19 +1772,6 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv } - @TestMetadata("j2k/tests/testData/ast/kotlinExclusion") - public static class KotlinExclusion extends AbstractJavaToKotlinConverterTest { - public void testAllFilesPresentInKotlinExclusion() throws Exception { - JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/kotlinExclusion"), Pattern.compile("^(.+)\\.java$"), true); - } - - @TestMetadata("kt-656.java") - public void testKt_656() throws Exception { - doTest("j2k/tests/testData/ast/kotlinExclusion/kt-656.java"); - } - - } - @TestMetadata("j2k/tests/testData/ast/labelStatement") public static class LabelStatement extends AbstractJavaToKotlinConverterTest { public void testAllFilesPresentInLabelStatement() throws Exception { @@ -1863,16 +1956,26 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/newClassExpression/genericClassInvocation.java"); } + @TestMetadata("newAnonymousClass.java") + public void testNewAnonymousClass() throws Exception { + doTest("j2k/tests/testData/ast/newClassExpression/newAnonymousClass.java"); + } + + @TestMetadata("newAnonymousClass2.java") + public void testNewAnonymousClass2() throws Exception { + doTest("j2k/tests/testData/ast/newClassExpression/newAnonymousClass2.java"); + } + + @TestMetadata("newAnonymousClass3.java") + public void testNewAnonymousClass3() throws Exception { + doTest("j2k/tests/testData/ast/newClassExpression/newAnonymousClass3.java"); + } + @TestMetadata("newClassByFullName.java") public void testNewClassByFullName() throws Exception { doTest("j2k/tests/testData/ast/newClassExpression/newClassByFullName.java"); } - @TestMetadata("newClassWithAnonymousScope.java") - public void testNewClassWithAnonymousScope() throws Exception { - doTest("j2k/tests/testData/ast/newClassExpression/newClassWithAnonymousScope.java"); - } - @TestMetadata("newInnerClass.java") public void testNewInnerClass() throws Exception { doTest("j2k/tests/testData/ast/newClassExpression/newInnerClass.java"); @@ -1926,6 +2029,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/nullability/FieldInitializedWithNull.java"); } + @TestMetadata("IndirectOverride.java") + public void testIndirectOverride() throws Exception { + doTest("j2k/tests/testData/ast/nullability/IndirectOverride.java"); + } + @TestMetadata("MethodInvokedWithNullArg.java") public void testMethodInvokedWithNullArg() throws Exception { doTest("j2k/tests/testData/ast/nullability/MethodInvokedWithNullArg.java"); @@ -1981,6 +2089,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/nullability/MethodReturnsTernaryNull.java"); } + @TestMetadata("NullableIntNoCrash.java") + public void testNullableIntNoCrash() throws Exception { + doTest("j2k/tests/testData/ast/nullability/NullableIntNoCrash.java"); + } + @TestMetadata("NullableMethodDotAccess.java") public void testNullableMethodDotAccess() throws Exception { doTest("j2k/tests/testData/ast/nullability/NullableMethodDotAccess.java"); @@ -1991,6 +2104,16 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/nullability/NullableVariableDotAccess.java"); } + @TestMetadata("OverrideWithInheritanceLoop.java") + public void testOverrideWithInheritanceLoop() throws Exception { + doTest("j2k/tests/testData/ast/nullability/OverrideWithInheritanceLoop.java"); + } + + @TestMetadata("Overrides.java") + public void testOverrides() throws Exception { + doTest("j2k/tests/testData/ast/nullability/Overrides.java"); + } + @TestMetadata("ParameterComparedWithNull.java") public void testParameterComparedWithNull() throws Exception { doTest("j2k/tests/testData/ast/nullability/ParameterComparedWithNull.java"); @@ -2203,6 +2326,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/returnStatement"), Pattern.compile("^(.+)\\.java$"), true); } + @TestMetadata("currentMethodBug.java") + public void testCurrentMethodBug() throws Exception { + doTest("j2k/tests/testData/ast/returnStatement/currentMethodBug.java"); + } + @TestMetadata("returnChar.java") public void testReturnChar() throws Exception { doTest("j2k/tests/testData/ast/returnStatement/returnChar.java"); @@ -2241,6 +2369,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv doTest("j2k/tests/testData/ast/settings/openByDefault.java"); } + @TestMetadata("specifyFieldTypeByDefault.java") + public void testSpecifyFieldTypeByDefault() throws Exception { + doTest("j2k/tests/testData/ast/settings/specifyFieldTypeByDefault.java"); + } + @TestMetadata("specifyLocalVariableTypeByDefault.java") public void testSpecifyLocalVariableTypeByDefault() throws Exception { doTest("j2k/tests/testData/ast/settings/specifyLocalVariableTypeByDefault.java"); @@ -2261,6 +2394,39 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv } + @TestMetadata("j2k/tests/testData/ast/staticMembers") + public static class StaticMembers extends AbstractJavaToKotlinConverterTest { + public void testAllFilesPresentInStaticMembers() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/staticMembers"), Pattern.compile("^(.+)\\.java$"), true); + } + + @TestMetadata("PrivateStaticMembers.java") + public void testPrivateStaticMembers() throws Exception { + doTest("j2k/tests/testData/ast/staticMembers/PrivateStaticMembers.java"); + } + + @TestMetadata("PrivateStaticMethods1.java") + public void testPrivateStaticMethods1() throws Exception { + doTest("j2k/tests/testData/ast/staticMembers/PrivateStaticMethods1.java"); + } + + @TestMetadata("PrivateStaticMethods2.java") + public void testPrivateStaticMethods2() throws Exception { + doTest("j2k/tests/testData/ast/staticMembers/PrivateStaticMethods2.java"); + } + + @TestMetadata("PrivateStaticMethods3.java") + public void testPrivateStaticMethods3() throws Exception { + doTest("j2k/tests/testData/ast/staticMembers/PrivateStaticMethods3.java"); + } + + @TestMetadata("PrivateStaticMethods4.java") + public void testPrivateStaticMethods4() throws Exception { + doTest("j2k/tests/testData/ast/staticMembers/PrivateStaticMethods4.java"); + } + + } + @TestMetadata("j2k/tests/testData/ast/superExpression") public static class SuperExpression extends AbstractJavaToKotlinConverterTest { public void testAllFilesPresentInSuperExpression() throws Exception { @@ -2361,6 +2527,34 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv } + @TestMetadata("j2k/tests/testData/ast/toKotlinClasses") + public static class ToKotlinClasses extends AbstractJavaToKotlinConverterTest { + public void testAllFilesPresentInToKotlinClasses() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/toKotlinClasses"), Pattern.compile("^(.+)\\.java$"), true); + } + + @TestMetadata("iterableAndIterator.java") + public void testIterableAndIterator() throws Exception { + doTest("j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator.java"); + } + + @TestMetadata("iterableAndIterator2.java") + public void testIterableAndIterator2() throws Exception { + doTest("j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator2.java"); + } + + @TestMetadata("iterableAndIterator3.java") + public void testIterableAndIterator3() throws Exception { + doTest("j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator3.java"); + } + + @TestMetadata("TypeParameterBound.java") + public void testTypeParameterBound() throws Exception { + doTest("j2k/tests/testData/ast/toKotlinClasses/TypeParameterBound.java"); + } + + } + @TestMetadata("j2k/tests/testData/ast/trait") public static class Trait extends AbstractJavaToKotlinConverterTest { @TestMetadata("abstactInterface.java") @@ -2452,6 +2646,64 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv } + @TestMetadata("j2k/tests/testData/ast/tryWithResource") + public static class TryWithResource extends AbstractJavaToKotlinConverterTest { + public void testAllFilesPresentInTryWithResource() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/tryWithResource"), Pattern.compile("^(.+)\\.java$"), true); + } + + @TestMetadata("Multiline.java") + public void testMultiline() throws Exception { + doTest("j2k/tests/testData/ast/tryWithResource/Multiline.java"); + } + + @TestMetadata("MultipleResources.java") + public void testMultipleResources() throws Exception { + doTest("j2k/tests/testData/ast/tryWithResource/MultipleResources.java"); + } + + @TestMetadata("Simple.java") + public void testSimple() throws Exception { + doTest("j2k/tests/testData/ast/tryWithResource/Simple.java"); + } + + @TestMetadata("WithCatch.java") + public void testWithCatch() throws Exception { + doTest("j2k/tests/testData/ast/tryWithResource/WithCatch.java"); + } + + @TestMetadata("WithCatchAndFinally.java") + public void testWithCatchAndFinally() throws Exception { + doTest("j2k/tests/testData/ast/tryWithResource/WithCatchAndFinally.java"); + } + + @TestMetadata("WithCatches.java") + public void testWithCatches() throws Exception { + doTest("j2k/tests/testData/ast/tryWithResource/WithCatches.java"); + } + + @TestMetadata("WithFinally.java") + public void testWithFinally() throws Exception { + doTest("j2k/tests/testData/ast/tryWithResource/WithFinally.java"); + } + + @TestMetadata("WithReturnAtEnd.java") + public void testWithReturnAtEnd() throws Exception { + doTest("j2k/tests/testData/ast/tryWithResource/WithReturnAtEnd.java"); + } + + @TestMetadata("WithReturnInAnonymousClass.java") + public void testWithReturnInAnonymousClass() throws Exception { + doTest("j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass.java"); + } + + @TestMetadata("WithReturnInAnonymousClass2.java") + public void testWithReturnInAnonymousClass2() throws Exception { + doTest("j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass2.java"); + } + + } + @TestMetadata("j2k/tests/testData/ast/typeCastExpression") public static class TypeCastExpression extends AbstractJavaToKotlinConverterTest { public void testAllFilesPresentInTypeCastExpression() throws Exception { @@ -2625,11 +2877,13 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv suite.addTestSuite(AssertStatement.class); suite.addTestSuite(AssignmentExpression.class); suite.addTestSuite(BinaryExpression.class); + suite.addTestSuite(Blocks.class); suite.addTestSuite(BoxedType.class); suite.addTestSuite(BreakStatement.class); suite.addTestSuite(CallChainExpression.class); suite.addTestSuite(Class.class); suite.addTestSuite(ClassExpression.class); + suite.addTestSuite(Comments.class); suite.addTestSuite(ConditionalExpression.class); suite.addTestSuite(Constructors.class); suite.addTestSuite(ContinueStatement.class); @@ -2650,7 +2904,6 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv suite.addTestSuite(IsOperator.class); suite.addTestSuite(Issues.class); suite.addTestSuite(KotlinApiAccess.class); - suite.addTestSuite(KotlinExclusion.class); suite.addTestSuite(LabelStatement.class); suite.addTestSuite(List.class); suite.addTestSuite(LiteralExpression.class); @@ -2670,13 +2923,16 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv suite.addTestSuite(ReturnStatement.class); suite.addTestSuite(Settings.class); suite.addTestSuite(StarProjectionType.class); + suite.addTestSuite(StaticMembers.class); suite.addTestSuite(SuperExpression.class); suite.addTestSuite(Switch.class); suite.addTestSuite(SynchronizedStatement.class); suite.addTestSuite(ThisExpression.class); suite.addTestSuite(ThrowStatement.class); + suite.addTestSuite(ToKotlinClasses.class); suite.addTestSuite(Trait.class); suite.addTestSuite(TryStatement.class); + suite.addTestSuite(TryWithResource.class); suite.addTestSuite(TypeCastExpression.class); suite.addTestSuite(TypeParameters.class); suite.addTestSuite(VarArg.class); diff --git a/j2k/tests/testData/JavaApi.java b/j2k/tests/testData/JavaApi.java new file mode 100644 index 00000000000..1da536be2ec --- /dev/null +++ b/j2k/tests/testData/JavaApi.java @@ -0,0 +1,58 @@ +package javaApi; + +import org.jetbrains.annotations.Nullable; + +import java.lang.Override; +import java.lang.String; + +public @interface Anon1 { + String[] value(); + String[] stringArray(); + int[] intArray(); + String string(); +} + +public @interface Anon2 { + String value(); + int intValue(); + char charValue(); +} + +public @interface Anon3 { + E e(); + String[] stringArray(); + String[] value(); +} + +public @interface Anon4 { + String[] value(); +} + +public @interface Anon5 { + int value(); +} + +public @interface Anon6 { + String[] value(); + int intValue() default 10; +} + +public @interface Anon7 { + Class[] value(); +} + +public @interface Anon8 { + Class[] classes(); +} + +public enum E { + A, B, C +} + +class Base { + public @Nullable String foo(@Nullable String s) { return s; } +} + +class Derived extends Base { + public String foo(String s) { return s; } +} diff --git a/j2k/tests/testData/KotlinApi.kt b/j2k/tests/testData/KotlinApi.kt index 344233b6959..21eb3270a7e 100644 --- a/j2k/tests/testData/KotlinApi.kt +++ b/j2k/tests/testData/KotlinApi.kt @@ -19,6 +19,8 @@ public open class KotlinClass { public trait KotlinTrait { public fun nullableFun(): String? public fun notNullableFun(): String + + public fun nonAbstractFun(): Int = 1 } public fun globalFunction(s: String): String = s diff --git a/j2k/tests/testData/ast/annotations/annotationUsages.java b/j2k/tests/testData/ast/annotations/annotationUsages.java new file mode 100644 index 00000000000..0ef69bb0679 --- /dev/null +++ b/j2k/tests/testData/ast/annotations/annotationUsages.java @@ -0,0 +1,29 @@ +//file +import javaApi.*; + +@Anon1(value = {"a"}, stringArray = {"b"}, intArray = {1, 2}, string = "x") +@Anon2(value = "a", intValue = 1, charValue = 'a') +@Anon3(e = E.A, stringArray = {}, value = {"a", "b"}) +@Anon4({"x", "y"}) +@Anon5(1) +@Anon6({"x", "y"}) +@Anon7({ String.class, StringBuilder.class }) +@Anon8(classes = { String.class, StringBuilder.class }) +class C { + @Anon5(1) @Deprecated private int field1 = 0; + + @Anon5(1) + private int field2 = 0; + + @Anon5(1) int field3 = 0; + + @Anon5(1) + int field4 = 0; + + @Anon6({}) + void foo(@Deprecated int p1, @Deprecated @Anon5(2) char p2) { + @Deprecated @Anon5(3) char c = 'a'; + } + + @Anon5(1) void bar(){} +} diff --git a/j2k/tests/testData/ast/annotations/annotationUsages.kt b/j2k/tests/testData/ast/annotations/annotationUsages.kt new file mode 100644 index 00000000000..93e135f82af --- /dev/null +++ b/j2k/tests/testData/ast/annotations/annotationUsages.kt @@ -0,0 +1,29 @@ +import javaApi.* + +Anon1(value = array("a"), stringArray = array("b"), intArray = intArray(1, 2), string = "x") +Anon2(value = "a", intValue = 1, charValue = 'a') +Anon3(e = E.A, stringArray = array(), value = *array("a", "b")) +Anon4("x", "y") +Anon5(1) +Anon6(array("x", "y")) +Anon7(javaClass(), javaClass()) +Anon8(classes = *array(javaClass(), javaClass())) +class C() { + Anon5(1) deprecated("") private val field1 = 0 + + Anon5(1) + private val field2 = 0 + + Anon5(1) var field3 = 0 + + Anon5(1) + var field4 = 0 + + Anon6(array()) + fun foo(deprecated("") p1: Int, deprecated("") Anon5(2) p2: Char) { + [deprecated("")] [Anon5(3)] val c = 'a' + } + + Anon5(1) fun bar() { + } +} diff --git a/j2k/tests/testData/ast/annotations/jetbrainsNotNull.kt b/j2k/tests/testData/ast/annotations/jetbrainsNotNull.kt index 7598605805e..826a768f9ba 100644 --- a/j2k/tests/testData/ast/annotations/jetbrainsNotNull.kt +++ b/j2k/tests/testData/ast/annotations/jetbrainsNotNull.kt @@ -3,10 +3,10 @@ package test public class Test(str: String) { - var myStr: String = "String2" + var myStr = "String2" public fun sout(str: String) { - System.out?.println(str) + System.out!!.println(str) } public fun dummy(str: String): String { diff --git a/j2k/tests/testData/ast/annotations/jetbrainsNotNullChainExpr.kt b/j2k/tests/testData/ast/annotations/jetbrainsNotNullChainExpr.kt index b3b71dabab0..8d6ab2860e1 100644 --- a/j2k/tests/testData/ast/annotations/jetbrainsNotNullChainExpr.kt +++ b/j2k/tests/testData/ast/annotations/jetbrainsNotNullChainExpr.kt @@ -15,8 +15,8 @@ class Bar() { class Test() { public fun test(barNotNull: Bar, barNullable: Bar?) { barNotNull.fooNotNull.execute() - barNotNull.fooNullable?.execute() - barNullable?.fooNotNull?.execute() - barNullable?.fooNullable?.execute() + barNotNull.fooNullable!!.execute() + barNullable!!.fooNotNull.execute() + barNullable!!.fooNullable!!.execute() } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/arrayInitializerExpression/javaLangDoubleArray.kt b/j2k/tests/testData/ast/arrayInitializerExpression/javaLangDoubleArray.kt index e45850509f1..d2060c45afe 100644 --- a/j2k/tests/testData/ast/arrayInitializerExpression/javaLangDoubleArray.kt +++ b/j2k/tests/testData/ast/arrayInitializerExpression/javaLangDoubleArray.kt @@ -1 +1 @@ -val a = array(1.0, 2.0, 3.0) \ No newline at end of file +val a = array(1.0, 2.0, 3.0) \ No newline at end of file diff --git a/j2k/tests/testData/ast/arrayInitializerExpression/javaLangFloatArray.kt b/j2k/tests/testData/ast/arrayInitializerExpression/javaLangFloatArray.kt index f7863159886..34498907cd2 100644 --- a/j2k/tests/testData/ast/arrayInitializerExpression/javaLangFloatArray.kt +++ b/j2k/tests/testData/ast/arrayInitializerExpression/javaLangFloatArray.kt @@ -1 +1 @@ -val a = array(1.0, 2.0, 3.0) \ No newline at end of file +val a = array(1.0, 2.0, 3.0) \ No newline at end of file diff --git a/j2k/tests/testData/ast/assertStatement/withStringDetail.kt b/j2k/tests/testData/ast/assertStatement/withStringDetail.kt index dbf44bd5eb8..720ccd99f52 100644 --- a/j2k/tests/testData/ast/assertStatement/withStringDetail.kt +++ b/j2k/tests/testData/ast/assertStatement/withStringDetail.kt @@ -1 +1 @@ -assert(true) { "string details" } \ No newline at end of file +assert(true, "string details") \ No newline at end of file diff --git a/j2k/tests/testData/ast/assertStatement/withStringDetail2.java b/j2k/tests/testData/ast/assertStatement/withStringDetail2.java new file mode 100644 index 00000000000..c8b9e98482f --- /dev/null +++ b/j2k/tests/testData/ast/assertStatement/withStringDetail2.java @@ -0,0 +1,2 @@ +//statement +assert true : "string details:" + x; \ No newline at end of file diff --git a/j2k/tests/testData/ast/assertStatement/withStringDetail2.kt b/j2k/tests/testData/ast/assertStatement/withStringDetail2.kt new file mode 100644 index 00000000000..97aa2c8f30f --- /dev/null +++ b/j2k/tests/testData/ast/assertStatement/withStringDetail2.kt @@ -0,0 +1 @@ +assert(true) { "string details:" + x } \ No newline at end of file diff --git a/j2k/tests/testData/ast/assignmentExpression/nullability-settings.kt b/j2k/tests/testData/ast/assignmentExpression/nullability-settings.kt index 907706ff69f..cf6a283fc4e 100644 --- a/j2k/tests/testData/ast/assignmentExpression/nullability-settings.kt +++ b/j2k/tests/testData/ast/assignmentExpression/nullability-settings.kt @@ -6,6 +6,6 @@ class Foo() { fun foo(o: BitSet?) { val o2: BitSet? = o val foo: Int = 0 - foo = o2?.size()!! + foo = o2!!.size() } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/blocks/Blocks.java b/j2k/tests/testData/ast/blocks/Blocks.java new file mode 100644 index 00000000000..b6d6c86aebe --- /dev/null +++ b/j2k/tests/testData/ast/blocks/Blocks.java @@ -0,0 +1,16 @@ +//method +void foo() { + { + int a = 1; + bar(a); + } + + { + int a = 2; + bar(a); + } + + { + bar(3); + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/blocks/Blocks.kt b/j2k/tests/testData/ast/blocks/Blocks.kt new file mode 100644 index 00000000000..f1644d4da0e --- /dev/null +++ b/j2k/tests/testData/ast/blocks/Blocks.kt @@ -0,0 +1,13 @@ +fun foo() { + run { + val a = 1 + bar(a) + } + + run { + val a = 2 + bar(a) + } + + run { bar(3) } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/callChainExpression/libraryMethodCallFromInstance-settings.kt b/j2k/tests/testData/ast/callChainExpression/libraryMethodCallFromInstance-settings.kt index 3a175bc155e..4225353cd8f 100644 --- a/j2k/tests/testData/ast/callChainExpression/libraryMethodCallFromInstance-settings.kt +++ b/j2k/tests/testData/ast/callChainExpression/libraryMethodCallFromInstance-settings.kt @@ -13,9 +13,9 @@ class User() { fun main() { val lib: Library = Library() lib.call() - lib.getString()?.isEmpty() + lib.getString()!!.isEmpty() Library().call() - Library().getString()?.isEmpty() + Library().getString()!!.isEmpty() } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/class/classWithFields.kt b/j2k/tests/testData/ast/class/classWithFields.kt index 134d4d62abf..c562a60dcfa 100644 --- a/j2k/tests/testData/ast/class/classWithFields.kt +++ b/j2k/tests/testData/ast/class/classWithFields.kt @@ -1,4 +1,4 @@ class T() { - var a: String = "abc" - var b: Int = 10 + var a = "abc" + var b = 10 } \ No newline at end of file diff --git a/j2k/tests/testData/ast/class/classWithMultiplyFields.kt b/j2k/tests/testData/ast/class/classWithMultiplyFields.kt index 19cbb56f9f5..48202044e1e 100644 --- a/j2k/tests/testData/ast/class/classWithMultiplyFields.kt +++ b/j2k/tests/testData/ast/class/classWithMultiplyFields.kt @@ -1,5 +1,5 @@ class T() { var a: String = 0 var b: String = 0 - var c: String = "abc" + var c = "abc" } \ No newline at end of file diff --git a/j2k/tests/testData/ast/class/innerClassInInterface.java b/j2k/tests/testData/ast/class/innerClassInInterface.java new file mode 100644 index 00000000000..9e5d2fa1dbf --- /dev/null +++ b/j2k/tests/testData/ast/class/innerClassInInterface.java @@ -0,0 +1,4 @@ +//file +interface A { + class B {} +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/class/innerClassInInterface.kt b/j2k/tests/testData/ast/class/innerClassInInterface.kt new file mode 100644 index 00000000000..bf27807d862 --- /dev/null +++ b/j2k/tests/testData/ast/class/innerClassInInterface.kt @@ -0,0 +1,3 @@ +trait A { + public class B() +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/class/innerEmptyClass.kt b/j2k/tests/testData/ast/class/innerEmptyClass.kt index 316afd78138..b87118b1c28 100644 --- a/j2k/tests/testData/ast/class/innerEmptyClass.kt +++ b/j2k/tests/testData/ast/class/innerEmptyClass.kt @@ -1,3 +1,3 @@ class A() { - class B() + inner class B() } \ No newline at end of file diff --git a/j2k/tests/testData/ast/class/innerEnum.java b/j2k/tests/testData/ast/class/innerEnum.java new file mode 100644 index 00000000000..ae26b82b66b --- /dev/null +++ b/j2k/tests/testData/ast/class/innerEnum.java @@ -0,0 +1,8 @@ +//file +class A { + enum E { + A, + B, + C + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/class/innerEnum.kt b/j2k/tests/testData/ast/class/innerEnum.kt new file mode 100644 index 00000000000..98202a1484b --- /dev/null +++ b/j2k/tests/testData/ast/class/innerEnum.kt @@ -0,0 +1,7 @@ +class A() { + enum class E { + A + B + C + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/class/innerInterface.java b/j2k/tests/testData/ast/class/innerInterface.java new file mode 100644 index 00000000000..5031f3345b2 --- /dev/null +++ b/j2k/tests/testData/ast/class/innerInterface.java @@ -0,0 +1,4 @@ +//file +class A { + interface I {} +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/class/innerInterface.kt b/j2k/tests/testData/ast/class/innerInterface.kt new file mode 100644 index 00000000000..344a7196097 --- /dev/null +++ b/j2k/tests/testData/ast/class/innerInterface.kt @@ -0,0 +1,3 @@ +class A() { + trait I +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/class/innerStaticClass.kt b/j2k/tests/testData/ast/class/innerStaticClass.kt index 21c9a0e2e11..86108fe20b2 100644 --- a/j2k/tests/testData/ast/class/innerStaticClass.kt +++ b/j2k/tests/testData/ast/class/innerStaticClass.kt @@ -1,5 +1,3 @@ class S() { - class object { - class Inner() - } + class Inner() } \ No newline at end of file diff --git a/j2k/tests/testData/ast/class/kt-639.kt b/j2k/tests/testData/ast/class/kt-639.kt index ddaee0f171b..b9d664921b9 100644 --- a/j2k/tests/testData/ast/class/kt-639.kt +++ b/j2k/tests/testData/ast/class/kt-639.kt @@ -4,11 +4,11 @@ import java.util.HashMap class Test private() { class object { - fun init(): Test { + fun create(): Test { val __ = Test() return __ } - fun init(s: String): Test { + fun create(s: String): Test { val __ = Test() return __ } @@ -20,7 +20,7 @@ class User() { val m = HashMap(1) val m2 = HashMap(10) - val t1 = Test.init() - val t2 = Test.init("") + val t1 = Test.create() + val t2 = Test.create("") } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/class/oneStaticFieldOneNonStatic.kt b/j2k/tests/testData/ast/class/oneStaticFieldOneNonStatic.kt index fa2ebfe0b04..118a135c79c 100644 --- a/j2k/tests/testData/ast/class/oneStaticFieldOneNonStatic.kt +++ b/j2k/tests/testData/ast/class/oneStaticFieldOneNonStatic.kt @@ -4,6 +4,6 @@ class S() { } class object { - var myI: Int = 10 + var myI = 10 } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/comments/comments.java b/j2k/tests/testData/ast/comments/comments.java new file mode 100644 index 00000000000..61c1099cc74 --- /dev/null +++ b/j2k/tests/testData/ast/comments/comments.java @@ -0,0 +1,26 @@ +//file +package foo; // we use package 'foo' + +// imports: +import java.util.ArrayList; // we need ArrayList + +// let's declare a class: +class A /* just a sample name*/ implements Runnable /* let's implement Runnable */ { + void foo /* again a sample name */(int p /* parameter p */, char c /* parameter c */) { + // let's print something: + System.out.println("1"); // print 1 + System.out.println("2"); // print 2 + + System.out.println("3"); // print 3 + + // end of printing + + if (p > 0) { // do this only when p > 0 + // we print 4 and return + System.out.println("3"); + return; // do not continue + } + + // some code to be added + } +} // end of class A \ No newline at end of file diff --git a/j2k/tests/testData/ast/comments/comments.kt b/j2k/tests/testData/ast/comments/comments.kt new file mode 100644 index 00000000000..8fbef48f875 --- /dev/null +++ b/j2k/tests/testData/ast/comments/comments.kt @@ -0,0 +1,30 @@ +package foo + +// we use package 'foo' + +// imports: +import java.util.ArrayList + +// we need ArrayList + +// let's declare a class: +class A /* just a sample name*/() : Runnable /* let's implement Runnable */ { + fun foo/* again a sample name */(p: Int /* parameter p */, c: Char /* parameter c */) { + // let's print something: + System.out.println("1") // print 1 + System.out.println("2") // print 2 + + System.out.println("3") // print 3 + + // end of printing + + if (p > 0) { + // do this only when p > 0 + // we print 4 and return + System.out.println("3") + return // do not continue + } + + // some code to be added + } +} // end of class A \ No newline at end of file diff --git a/j2k/tests/testData/ast/comments/comments.kt.todo b/j2k/tests/testData/ast/comments/comments.kt.todo new file mode 100644 index 00000000000..c2b1c4c52da --- /dev/null +++ b/j2k/tests/testData/ast/comments/comments.kt.todo @@ -0,0 +1,25 @@ +package foo // we use package 'foo' + +// imports: +import java.util.ArrayList // we need ArrayList + +// let's declare a class: +class A /* just a sample name*/() : Runnable /* let's implement Runnable */ { + fun foo /* again a sample name */( p: Int /* parameter p */, c: Char /* parameter c */) { + // let's print something: + System.out.println("1") // print 1 + System.out.println("2") // print 2 + + System.out.println("3") // print 3 + + // end of printing + + if (p > 0) { // do this only when p > 0 + // we print 4 and return + System.out.println("3") + return // do not continue + } + + // some code to be added + } +} // end of class A diff --git a/j2k/tests/testData/ast/comments/comments2.java b/j2k/tests/testData/ast/comments/comments2.java new file mode 100644 index 00000000000..b9de99b91ed --- /dev/null +++ b/j2k/tests/testData/ast/comments/comments2.java @@ -0,0 +1,20 @@ +//file +package foo; + +class A { + void/* nothing to return */ foo(/* no parameters at all */) { + // let declare a variable + // with 2 comments before + int/*int*/ a /* it's a */ = 2 /* it's 2 */ + 1 /* it's 1 */; // variable a declared + } // end of foo + + int/* we return int*/ foo(int/*int*/ p/* parameter p */) { /* body is empty */ } + + private/*it's private*/ int field = 0; + + public /*it's public*/ char foo() { } + + protected/*it's protected*/ void foo() { } + + public/*it's public*/ static/*and static*/ final/*and final*/ int C = 1; +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/comments/comments2.kt b/j2k/tests/testData/ast/comments/comments2.kt new file mode 100644 index 00000000000..0760fa55820 --- /dev/null +++ b/j2k/tests/testData/ast/comments/comments2.kt @@ -0,0 +1,26 @@ +package foo + +class A() { + fun /* nothing to return */ foo(/* no parameters at all */) { + // let declare a variable + // with 2 comments before + val /*int*/ a /* it's a */ = 2 /* it's 2 */ + 1 /* it's 1 */ // variable a declared + } // end of foo + + fun /* we return int*/ foo(/*int*/ p: Int/* parameter p */): Int { + /* body is empty */ + } + + private /*it's private*/ val field = 0 + + public /*it's public*/ fun foo(): Char { + } + + protected /*it's protected*/ fun foo() { + } + + class object { + + public /*it's public*//*and static*//*and final*/ val C: Int = 1 + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/comments/fieldWithEndOfLineComment.java b/j2k/tests/testData/ast/comments/fieldWithEndOfLineComment.java new file mode 100644 index 00000000000..340ae032186 --- /dev/null +++ b/j2k/tests/testData/ast/comments/fieldWithEndOfLineComment.java @@ -0,0 +1,4 @@ +//file +class A { + private boolean isOpen = true; // ideally should be atomic boolean +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/comments/fieldWithEndOfLineComment.kt b/j2k/tests/testData/ast/comments/fieldWithEndOfLineComment.kt new file mode 100644 index 00000000000..4390146f416 --- /dev/null +++ b/j2k/tests/testData/ast/comments/fieldWithEndOfLineComment.kt @@ -0,0 +1,3 @@ +class A() { + private val isOpen = true // ideally should be atomic boolean +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/comments/fieldsInitializedFromParams.java b/j2k/tests/testData/ast/comments/fieldsInitializedFromParams.java new file mode 100644 index 00000000000..efcc082ae6f --- /dev/null +++ b/j2k/tests/testData/ast/comments/fieldsInitializedFromParams.java @@ -0,0 +1,17 @@ +//file +class C { + private final int p1; // field p1 + + /** + * Field myP2 + */ + private final int myP2; + + /* Field p3 */ public int p3; + + public C(int p1 /* parameter p1 */, int p2, int p3) { + this.p1 = p1; + myP2 = p2; + this.p3 = p3; + } +} diff --git a/j2k/tests/testData/ast/comments/fieldsInitializedFromParams.kt b/j2k/tests/testData/ast/comments/fieldsInitializedFromParams.kt new file mode 100644 index 00000000000..f8654e83f46 --- /dev/null +++ b/j2k/tests/testData/ast/comments/fieldsInitializedFromParams.kt @@ -0,0 +1,6 @@ +class C(private val p1: Int /* parameter p1 */ // field p1 + , + /** + * Field myP2 + */ + private val myP2: Int, /* Field p3 */ public var p3: Int) diff --git a/j2k/tests/testData/ast/constructors/allCallsPrimary.kt b/j2k/tests/testData/ast/constructors/allCallsPrimary.kt index 59223e27a74..df84622b5c6 100644 --- a/j2k/tests/testData/ast/constructors/allCallsPrimary.kt +++ b/j2k/tests/testData/ast/constructors/allCallsPrimary.kt @@ -1,12 +1,12 @@ class C(arg1: Int, arg2: Int, arg3: Int) { class object { - fun init(arg1: Int, arg2: Int): C { + fun create(arg1: Int, arg2: Int): C { val __ = C(arg1, arg2, 0) return __ } - fun init(arg1: Int): C { + fun create(arg1: Int): C { val __ = C(arg1, 0, 0) return __ } @@ -17,8 +17,8 @@ public class User() { class object { public fun main() { val c1 = C(100, 100, 100) - val c2 = C.init(100, 100) - val c3 = C.init(100) + val c2 = C.create(100, 100) + val c3 = C.create(100) } } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/constructors/allCallsPrimary2.kt b/j2k/tests/testData/ast/constructors/allCallsPrimary2.kt index c1249fd7180..d52b169f49d 100644 --- a/j2k/tests/testData/ast/constructors/allCallsPrimary2.kt +++ b/j2k/tests/testData/ast/constructors/allCallsPrimary2.kt @@ -9,14 +9,14 @@ class C(val myArg1: Int) { class object { - fun init(arg1: Int, arg2: Int, arg3: Int): C { + fun create(arg1: Int, arg2: Int, arg3: Int): C { val __ = C(arg1) __.myArg2 = arg2 __.myArg3 = arg3 return __ } - fun init(arg1: Int, arg2: Int): C { + fun create(arg1: Int, arg2: Int): C { val __ = C(arg1) __.myArg2 = arg2 __.myArg3 = 0 @@ -28,8 +28,8 @@ class C(val myArg1: Int) { public class User() { class object { public fun main() { - val c1 = C.init(100, 100, 100) - val c2 = C.init(100, 100) + val c1 = C.create(100, 100, 100) + val c2 = C.create(100, 100) val c3 = C(100) } } diff --git a/j2k/tests/testData/ast/constructors/genericIdentifier.kt b/j2k/tests/testData/ast/constructors/genericIdentifier.kt index 0bbd7ccfb40..e569d2ca8b5 100644 --- a/j2k/tests/testData/ast/constructors/genericIdentifier.kt +++ b/j2k/tests/testData/ast/constructors/genericIdentifier.kt @@ -1,5 +1,5 @@ -public class Identifier private(private val myName: T, private var myHasDollar: Boolean) { - private var myNullable: Boolean = true +public class Identifier private(private val myName: T, private val myHasDollar: Boolean) { + private var myNullable = true public fun getName(): T { return myName @@ -7,18 +7,18 @@ public class Identifier private(private val myName: T, private var myHasDolla class object { - public fun init(name: T): Identifier { + public fun create(name: T): Identifier { val __ = Identifier(name, false) return __ } - public fun init(name: T, isNullable: Boolean): Identifier { + public fun create(name: T, isNullable: Boolean): Identifier { val __ = Identifier(name, false) __.myNullable = isNullable return __ } - public fun init(name: T, hasDollar: Boolean, isNullable: Boolean): Identifier { + public fun create(name: T, hasDollar: Boolean, isNullable: Boolean): Identifier { val __ = Identifier(name, hasDollar) __.myNullable = isNullable return __ @@ -29,9 +29,9 @@ public class Identifier private(private val myName: T, private var myHasDolla public class User() { class object { public fun main() { - val i1 = Identifier.init("name", false, true) - val i2 = Identifier.init("name", false) - val i3 = Identifier.init("name") + val i1 = Identifier.create("name", false, true) + val i2 = Identifier.create("name", false) + val i3 = Identifier.create("name") } } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/constructors/identifier.kt b/j2k/tests/testData/ast/constructors/identifier.kt index 5e6c067fe8f..3a3e6e9be5f 100644 --- a/j2k/tests/testData/ast/constructors/identifier.kt +++ b/j2k/tests/testData/ast/constructors/identifier.kt @@ -1,5 +1,5 @@ -public class Identifier private(private val myName: String, private var myHasDollar: Boolean) { - private var myNullable: Boolean = true +public class Identifier private(private val myName: String, private val myHasDollar: Boolean) { + private var myNullable = true public fun getName(): String { return myName @@ -7,18 +7,18 @@ public class Identifier private(private val myName: String, private var myHasDol class object { - public fun init(name: String): Identifier { + public fun create(name: String): Identifier { val __ = Identifier(name, false) return __ } - public fun init(name: String, isNullable: Boolean): Identifier { + public fun create(name: String, isNullable: Boolean): Identifier { val __ = Identifier(name, false) __.myNullable = isNullable return __ } - public fun init(name: String, hasDollar: Boolean, isNullable: Boolean): Identifier { + public fun create(name: String, hasDollar: Boolean, isNullable: Boolean): Identifier { val __ = Identifier(name, hasDollar) __.myNullable = isNullable return __ @@ -29,9 +29,9 @@ public class Identifier private(private val myName: String, private var myHasDol public class User() { class object { public fun main() { - val i1 = Identifier.init("name", false, true) - val i2 = Identifier.init("name", false) - val i3 = Identifier.init("name") + val i1 = Identifier.create("name", false, true) + val i2 = Identifier.create("name", false) + val i3 = Identifier.create("name") } } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/constructors/privateConstructors.kt b/j2k/tests/testData/ast/constructors/privateConstructors.kt index 884b005389f..60c966bb8ac 100644 --- a/j2k/tests/testData/ast/constructors/privateConstructors.kt +++ b/j2k/tests/testData/ast/constructors/privateConstructors.kt @@ -1,14 +1,14 @@ class C private(arg1: Int, arg2: Int, arg3: Int) { class object { - private fun init(arg1: Int, arg2: Int): C { + private fun create(arg1: Int, arg2: Int): C { val __ = C(arg1, arg2, 0) return __ } - public fun init(arg1: Int): C { + public fun create(arg1: Int): C { val __ = C(arg1, 0, 0) return __ } } -} \ No newline at end of file +} diff --git a/j2k/tests/testData/ast/constructors/withManyDefaultParams.java b/j2k/tests/testData/ast/constructors/withManyDefaultParams.java index 2940814308f..659c10b522c 100644 --- a/j2k/tests/testData/ast/constructors/withManyDefaultParams.java +++ b/j2k/tests/testData/ast/constructors/withManyDefaultParams.java @@ -1,13 +1,13 @@ //file public class Test { private final String myName; - private boolean a; - private double b; - private float c; - private long d; - private int e; - private short f; - private char g; + boolean a; + double b; + float c; + long d; + int e; + protected short f; + protected char g; public Test() {} diff --git a/j2k/tests/testData/ast/constructors/withManyDefaultParams.kt b/j2k/tests/testData/ast/constructors/withManyDefaultParams.kt index 9a651b687c1..5afaeb3f3d6 100644 --- a/j2k/tests/testData/ast/constructors/withManyDefaultParams.kt +++ b/j2k/tests/testData/ast/constructors/withManyDefaultParams.kt @@ -1,17 +1,16 @@ -public class Test private(private val myName: String, private var a: Boolean, private var b: Double, private var c: Float, private var d: Long, private var e: Int, private var f: Short, private var g: Char) { +public class Test private(private val myName: String, var a: Boolean, var b: Double, var c: Float, var d: Long, var e: Int, protected var f: Short, protected var g: Char) { class object { - public fun init(): Test { + public fun create(): Test { val __ = Test(0, false, 0.toDouble(), 0.toFloat(), 0, 0, 0, ' ') return __ } - public fun init(name: String): Test { + public fun create(name: String): Test { val __ = Test(foo(name), false, 0.toDouble(), 0.toFloat(), 0, 0, 0, ' ') return __ } - fun foo(n: String): String { return "" } @@ -21,7 +20,7 @@ public class Test private(private val myName: String, private var a: Boolean, pr public class User() { class object { public fun main() { - val t = Test.init("name") + val t = Test.create("name") } } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/enum/emptyEnum.kt b/j2k/tests/testData/ast/enum/emptyEnum.kt index cf0c22de5bd..7bce4477266 100644 --- a/j2k/tests/testData/ast/enum/emptyEnum.kt +++ b/j2k/tests/testData/ast/enum/emptyEnum.kt @@ -1 +1 @@ -enum class A {} \ No newline at end of file +enum class A \ No newline at end of file diff --git a/j2k/tests/testData/ast/enum/enumImplementsOneInterface.kt b/j2k/tests/testData/ast/enum/enumImplementsOneInterface.kt index 09b2e590bef..da87d3bc15c 100644 --- a/j2k/tests/testData/ast/enum/enumImplementsOneInterface.kt +++ b/j2k/tests/testData/ast/enum/enumImplementsOneInterface.kt @@ -1 +1 @@ -enum class A : I {} \ No newline at end of file +enum class A : I \ No newline at end of file diff --git a/j2k/tests/testData/ast/enum/enumImplementsSeveralInterfaces.kt b/j2k/tests/testData/ast/enum/enumImplementsSeveralInterfaces.kt index 183b15c4fff..7aef4bc20ed 100644 --- a/j2k/tests/testData/ast/enum/enumImplementsSeveralInterfaces.kt +++ b/j2k/tests/testData/ast/enum/enumImplementsSeveralInterfaces.kt @@ -1 +1 @@ -enum class A : I0, I1, I2 {} \ No newline at end of file +enum class A : I0, I1, I2 \ No newline at end of file diff --git a/j2k/tests/testData/ast/enum/enumWithNameField.kt b/j2k/tests/testData/ast/enum/enumWithNameField.kt index 4dbfe1f26ac..578630d8058 100644 --- a/j2k/tests/testData/ast/enum/enumWithNameField.kt +++ b/j2k/tests/testData/ast/enum/enumWithNameField.kt @@ -1,4 +1,4 @@ enum class E { I - private var name: String = 0 + private val name: String = 0 } \ No newline at end of file diff --git a/j2k/tests/testData/ast/enum/fieldsWithPrimaryPrivateConstructor.kt b/j2k/tests/testData/ast/enum/fieldsWithPrimaryPrivateConstructor.kt index 53ff728122c..83a774702ba 100644 --- a/j2k/tests/testData/ast/enum/fieldsWithPrimaryPrivateConstructor.kt +++ b/j2k/tests/testData/ast/enum/fieldsWithPrimaryPrivateConstructor.kt @@ -1,4 +1,4 @@ -enum class Color private(private var code: Int) { +enum class Color private(private val code: Int) { WHITE : Color(21) BLACK : Color(22) RED : Color(23) diff --git a/j2k/tests/testData/ast/enum/internalEnum.kt b/j2k/tests/testData/ast/enum/internalEnum.kt index 04f0bcf787a..6153151d301 100644 --- a/j2k/tests/testData/ast/enum/internalEnum.kt +++ b/j2k/tests/testData/ast/enum/internalEnum.kt @@ -1 +1 @@ -enum class Test {} \ No newline at end of file +enum class Test \ No newline at end of file diff --git a/j2k/tests/testData/ast/enum/primaryPrivateConstructor.kt b/j2k/tests/testData/ast/enum/primaryPrivateConstructor.kt index 583a45b4a47..838467a0bff 100644 --- a/j2k/tests/testData/ast/enum/primaryPrivateConstructor.kt +++ b/j2k/tests/testData/ast/enum/primaryPrivateConstructor.kt @@ -1,6 +1,6 @@ package demo -enum class Color private(private var code: Int) { +enum class Color private(private val code: Int) { public fun getCode(): Int { return code diff --git a/j2k/tests/testData/ast/enum/privateEnum.kt b/j2k/tests/testData/ast/enum/privateEnum.kt index 3dc188a912b..9d651c5ae4a 100644 --- a/j2k/tests/testData/ast/enum/privateEnum.kt +++ b/j2k/tests/testData/ast/enum/privateEnum.kt @@ -1 +1 @@ -private enum class Test {} \ No newline at end of file +private enum class Test \ No newline at end of file diff --git a/j2k/tests/testData/ast/enum/protectedEnum.kt b/j2k/tests/testData/ast/enum/protectedEnum.kt index 0cfa23e3ab5..064c2ca3809 100644 --- a/j2k/tests/testData/ast/enum/protectedEnum.kt +++ b/j2k/tests/testData/ast/enum/protectedEnum.kt @@ -1 +1 @@ -protected enum class Test {} \ No newline at end of file +protected enum class Test \ No newline at end of file diff --git a/j2k/tests/testData/ast/enum/publicEnum.kt b/j2k/tests/testData/ast/enum/publicEnum.kt index 0059e39d75d..8fc2d84c388 100644 --- a/j2k/tests/testData/ast/enum/publicEnum.kt +++ b/j2k/tests/testData/ast/enum/publicEnum.kt @@ -1 +1 @@ -public enum class Test {} \ No newline at end of file +public enum class Test \ No newline at end of file diff --git a/j2k/tests/testData/ast/field/classChildExtendsBase.kt b/j2k/tests/testData/ast/field/classChildExtendsBase.kt index 13bc6b8db49..c3cc9fc054a 100644 --- a/j2k/tests/testData/ast/field/classChildExtendsBase.kt +++ b/j2k/tests/testData/ast/field/classChildExtendsBase.kt @@ -1,7 +1,7 @@ class Base() { - private var myFirst: String = 0 + private val myFirst: String = 0 } class Child() : Base() { - private var mySecond: String = 0 + private val mySecond: String = 0 } \ No newline at end of file diff --git a/j2k/tests/testData/ast/field/privateField.kt b/j2k/tests/testData/ast/field/privateField.kt index f321996b3fe..f3e87b44ca0 100644 --- a/j2k/tests/testData/ast/field/privateField.kt +++ b/j2k/tests/testData/ast/field/privateField.kt @@ -1,3 +1,3 @@ class C() { - private var f: Foo = 0 + private val f: Foo = 0 } \ No newline at end of file diff --git a/j2k/tests/testData/ast/field/specifyType.java b/j2k/tests/testData/ast/field/specifyType.java new file mode 100644 index 00000000000..14a0e0cf7db --- /dev/null +++ b/j2k/tests/testData/ast/field/specifyType.java @@ -0,0 +1,29 @@ +//file +import org.jetbrains.annotations.Nullable; +import java.util.*; + +class A { + private final List field1 = new ArrayList(); + final List field2 = new ArrayList(); + public final int field3 = 0; + protected final int field4 = 0; + + private List field5 = new ArrayList(); + List field6 = new ArrayList(); + + private int field7 = 0; + int field8 = 0; + + @Nullable private String field9 = "a" + @Nullable private String field10 = foo(); + + String foo() { return "x"; } + + void bar() { + field5 = new ArrayList(); + field7++; + field8++; + field9 = null; + field10 = null; + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/field/specifyType.kt b/j2k/tests/testData/ast/field/specifyType.kt new file mode 100644 index 00000000000..57d4029693f --- /dev/null +++ b/j2k/tests/testData/ast/field/specifyType.kt @@ -0,0 +1,30 @@ +import java.util.* +import kotlin.List + +class A() { + private val field1 = ArrayList() + val field2: List = ArrayList() + public val field3: Int = 0 + protected val field4: Int = 0 + + private var field5: List = ArrayList() + var field6: List = ArrayList() + + private var field7 = 0 + var field8 = 0 + + private var field9: String? = "a" + private var field10: String? = foo() + + fun foo(): String { + return "x" + } + + fun bar() { + field5 = ArrayList() + field7++ + field8++ + field9 = null + field10 = null + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/field/valOrVar.java b/j2k/tests/testData/ast/field/valOrVar.java new file mode 100644 index 00000000000..02ccbef2060 --- /dev/null +++ b/j2k/tests/testData/ast/field/valOrVar.java @@ -0,0 +1,29 @@ +//file +class A { + private final int field1 = 0; + private int field2 = 0; + private int field3 = 0; + final int field4 = 0; + int field5 = 0; + private int field6; + private int field7; + private int field8; + private int field9; + private int field10; + private int field11; + + A(int p1, int p2, A a) { + field6 = p1; + field7 = 10; + this.field8 = p2; + this.field9 = 10; + if (p1 > 0) { + this.field10 = 10; + } + a.field11 = 10; + } + + void foo() { + field3 = field2; + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/field/valOrVar.kt b/j2k/tests/testData/ast/field/valOrVar.kt new file mode 100644 index 00000000000..182656bca28 --- /dev/null +++ b/j2k/tests/testData/ast/field/valOrVar.kt @@ -0,0 +1,24 @@ +class A(private val field6: Int, private val field8: Int, a: A) { + private val field1 = 0 + private val field2 = 0 + private var field3 = 0 + val field4 = 0 + var field5 = 0 + private val field7: Int + private val field9: Int + private var field10: Int = 0 + private var field11: Int = 0 + + fun foo() { + field3 = field2 + } + + { + field7 = 10 + this.field9 = 10 + if (field6 > 0) { + this.field10 = 10 + } + a.field11 = 10 + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/field/valWithInit.kt b/j2k/tests/testData/ast/field/valWithInit.kt index 2d120001aa4..beb1395d375 100644 --- a/j2k/tests/testData/ast/field/valWithInit.kt +++ b/j2k/tests/testData/ast/field/valWithInit.kt @@ -1,3 +1,3 @@ class C() { - val f: Foo = Foo(1, 2) + val f = Foo(1, 2) } \ No newline at end of file diff --git a/j2k/tests/testData/ast/field/varWithInit.kt b/j2k/tests/testData/ast/field/varWithInit.kt index 9238f03f782..ffed0dcc3a5 100644 --- a/j2k/tests/testData/ast/field/varWithInit.kt +++ b/j2k/tests/testData/ast/field/varWithInit.kt @@ -1,3 +1,3 @@ class C() { - var f: Foo = Foo(1, 2) + var f = Foo(1, 2) } \ No newline at end of file diff --git a/j2k/tests/testData/ast/for/commonCaseForTest.kt b/j2k/tests/testData/ast/for/commonCaseForTest.kt index 93765cdb4f9..8efe40b3183 100644 --- a/j2k/tests/testData/ast/for/commonCaseForTest.kt +++ b/j2k/tests/testData/ast/for/commonCaseForTest.kt @@ -1,9 +1,7 @@ -{ +run { init() while (condition()) { body() - { - update() - } + update() } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/for/forRangeWithBlock.java b/j2k/tests/testData/ast/for/forRangeWithBlock.java new file mode 100644 index 00000000000..255ff0538ac --- /dev/null +++ b/j2k/tests/testData/ast/for/forRangeWithBlock.java @@ -0,0 +1,3 @@ +//statement +int[] array = new int[10]; +for (int i = 0; i < 10; i++) {array[i] = i;} \ No newline at end of file diff --git a/j2k/tests/testData/ast/for/forRangeWithBlock.kt b/j2k/tests/testData/ast/for/forRangeWithBlock.kt new file mode 100644 index 00000000000..69ad99b50a8 --- /dev/null +++ b/j2k/tests/testData/ast/for/forRangeWithBlock.kt @@ -0,0 +1,4 @@ +val array = IntArray(10) +for (i in 0..10 - 1) { + array[i] = i +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/for/forWithBlock.java b/j2k/tests/testData/ast/for/forWithBlock.java index 255ff0538ac..c648fa84a2a 100644 --- a/j2k/tests/testData/ast/for/forWithBlock.java +++ b/j2k/tests/testData/ast/for/forWithBlock.java @@ -1,3 +1,5 @@ //statement -int[] array = new int[10]; -for (int i = 0; i < 10; i++) {array[i] = i;} \ No newline at end of file +for (int i = 0; i < 10; j++, i++) { + System.out.println(i); + System.out.println(j); +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/for/forWithBlock.kt b/j2k/tests/testData/ast/for/forWithBlock.kt index 69ad99b50a8..584bc4c0864 100644 --- a/j2k/tests/testData/ast/for/forWithBlock.kt +++ b/j2k/tests/testData/ast/for/forWithBlock.kt @@ -1,4 +1,9 @@ -val array = IntArray(10) -for (i in 0..10 - 1) { - array[i] = i +run { + val i = 0 + while (i < 10) { + System.out.println(i) + System.out.println(j) + j++ + i++ + } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/for/forWithBlockAndDoubleUpdate.kt b/j2k/tests/testData/ast/for/forWithBlockAndDoubleUpdate.kt index 45e8901650b..88022ed0bb3 100644 --- a/j2k/tests/testData/ast/for/forWithBlockAndDoubleUpdate.kt +++ b/j2k/tests/testData/ast/for/forWithBlockAndDoubleUpdate.kt @@ -1,13 +1,11 @@ -{ +run { val i = 0 while (i < 0) { - { + run { val i = 1 i++ } - { - j++ - i++ - } + j++ + i++ } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/for/forWithEmptyBlock.kt b/j2k/tests/testData/ast/for/forWithEmptyBlock.kt index fab9b579c8d..c321897d011 100644 --- a/j2k/tests/testData/ast/for/forWithEmptyBlock.kt +++ b/j2k/tests/testData/ast/for/forWithEmptyBlock.kt @@ -1,10 +1,7 @@ -{ +run { val i = 0 while (i < 0) { - {} - { - j++ - i++ - } + j++ + i++ } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/for/forWithNullCondition.kt b/j2k/tests/testData/ast/for/forWithNullCondition.kt index 068c816cfcf..5eb7f9d06c6 100644 --- a/j2k/tests/testData/ast/for/forWithNullCondition.kt +++ b/j2k/tests/testData/ast/for/forWithNullCondition.kt @@ -1,9 +1,7 @@ -{ +run { init() while (true) { body() - { - update() - } + update() } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/for/forWithNullInit.kt b/j2k/tests/testData/ast/for/forWithNullInit.kt index 9848b9962ac..f5bb9556fc6 100644 --- a/j2k/tests/testData/ast/for/forWithNullInit.kt +++ b/j2k/tests/testData/ast/for/forWithNullInit.kt @@ -1,8 +1,4 @@ -{ - while (condition()) { - body() - { - update() - } - } -} \ No newline at end of file +while (condition()) { + body() + update() +} diff --git a/j2k/tests/testData/ast/for/forWithNullUpdate.kt b/j2k/tests/testData/ast/for/forWithNullUpdate.kt index 7ca346555e1..d912eb3ed07 100644 --- a/j2k/tests/testData/ast/for/forWithNullUpdate.kt +++ b/j2k/tests/testData/ast/for/forWithNullUpdate.kt @@ -1,6 +1,4 @@ -{ +run { init() - while (condition()) { - body() - } + while (condition()) body() } \ No newline at end of file diff --git a/j2k/tests/testData/ast/for/forWithReturn.kt b/j2k/tests/testData/ast/for/forWithReturn.kt index cd07bc24e34..b618d0f6647 100644 --- a/j2k/tests/testData/ast/for/forWithReturn.kt +++ b/j2k/tests/testData/ast/for/forWithReturn.kt @@ -1,10 +1,8 @@ -{ +run { val i = 0 while (i < 0) { return i - { - j++ - i++ - } + j++ + i++ } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/for/infiniteFor.java b/j2k/tests/testData/ast/for/infiniteFor.java new file mode 100644 index 00000000000..4d1092db123 --- /dev/null +++ b/j2k/tests/testData/ast/for/infiniteFor.java @@ -0,0 +1,6 @@ +//method +void foo() { + for(;;) { + if (!stop()) break; + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/for/infiniteFor.kt b/j2k/tests/testData/ast/for/infiniteFor.kt new file mode 100644 index 00000000000..2bf8960aea3 --- /dev/null +++ b/j2k/tests/testData/ast/for/infiniteFor.kt @@ -0,0 +1,5 @@ +fun foo() { + while (true) { + if (!stop()) break + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/formatting/nonStaticMembers.kt b/j2k/tests/testData/ast/formatting/nonStaticMembers.kt index 32ea2da202f..33f676dfcd5 100644 --- a/j2k/tests/testData/ast/formatting/nonStaticMembers.kt +++ b/j2k/tests/testData/ast/formatting/nonStaticMembers.kt @@ -3,10 +3,9 @@ class F() { fun f1() { } - fun f2() { } - var i: Int = 0 + var i = 0 fun f3() { } diff --git a/j2k/tests/testData/ast/formatting/nonStaticMembersWithComments.kt b/j2k/tests/testData/ast/formatting/nonStaticMembersWithComments.kt index 163c5d65b5a..ef0256981a4 100644 --- a/j2k/tests/testData/ast/formatting/nonStaticMembersWithComments.kt +++ b/j2k/tests/testData/ast/formatting/nonStaticMembersWithComments.kt @@ -7,7 +7,6 @@ class F() { fun f1() { } - //c3 @@ -17,7 +16,7 @@ class F() { fun f2() { } - var i: Int = 0 + var i = 0 fun f3() { } diff --git a/j2k/tests/testData/ast/formatting/staticAndNonStaticMembersWithComments.kt b/j2k/tests/testData/ast/formatting/staticAndNonStaticMembersWithComments.kt index 7840a9982f7..71b50c0348e 100644 --- a/j2k/tests/testData/ast/formatting/staticAndNonStaticMembersWithComments.kt +++ b/j2k/tests/testData/ast/formatting/staticAndNonStaticMembersWithComments.kt @@ -1,6 +1,5 @@ class F() { - //c3 @@ -25,14 +24,14 @@ class F() { fun f1() { } - var i: Int = 0 + var i = 0 //c5 fun f5() { } - - //c6 - } + + //c6 + } \ No newline at end of file diff --git a/j2k/tests/testData/ast/formatting/staticMembersWithComments.kt b/j2k/tests/testData/ast/formatting/staticMembersWithComments.kt index c3197e5af63..2dc176320f2 100644 --- a/j2k/tests/testData/ast/formatting/staticMembersWithComments.kt +++ b/j2k/tests/testData/ast/formatting/staticMembersWithComments.kt @@ -8,7 +8,6 @@ class F() { fun f1() { } - //c3 @@ -18,11 +17,11 @@ class F() { fun f2() { } - var i: Int = 0 + var i = 0 fun f3() { } - - //c5 } + + //c5 } \ No newline at end of file diff --git a/j2k/tests/testData/ast/function/extendsBaseWhichExtendsObject.kt b/j2k/tests/testData/ast/function/extendsBaseWhichExtendsObject.kt index d5089fa31bc..57d95afb66e 100644 --- a/j2k/tests/testData/ast/function/extendsBaseWhichExtendsObject.kt +++ b/j2k/tests/testData/ast/function/extendsBaseWhichExtendsObject.kt @@ -5,10 +5,11 @@ class Test() : Base() { return super.hashCode() } - override fun equals(o: Any): Boolean { + override fun equals(o: Any?): Boolean { return super.equals(o) } + throws(javaClass()) override fun clone(): Any { return super.clone() } @@ -17,6 +18,7 @@ class Test() : Base() { return super.toString() } + throws(javaClass()) override fun finalize() { super.finalize() } @@ -27,10 +29,11 @@ class Base() { return super.hashCode() } - override fun equals(other: Any?): Boolean { + override fun equals(o: Any?): Boolean { return super.equals(o) } + throws(javaClass()) protected fun clone(): Any { return super.clone() } @@ -39,6 +42,7 @@ class Base() { return super.toString() } + throws(javaClass()) protected fun finalize() { super.finalize() } diff --git a/j2k/tests/testData/ast/function/overrideObject.kt b/j2k/tests/testData/ast/function/overrideObject.kt index 8d8a5919c85..fe55ec8bf2c 100644 --- a/j2k/tests/testData/ast/function/overrideObject.kt +++ b/j2k/tests/testData/ast/function/overrideObject.kt @@ -3,7 +3,7 @@ class X() { return super.hashCode() } - override fun equals(other: Any?): Boolean { + override fun equals(o: Any?): Boolean { return super.equals(o) } @@ -11,12 +11,14 @@ class X() { return super.toString() } + throws(javaClass()) protected fun clone(): Any { return super.clone() } } class Y() : Thread() { + throws(javaClass()) override fun clone(): Any { return super.clone() } diff --git a/j2k/tests/testData/ast/function/overrideObject2.kt b/j2k/tests/testData/ast/function/overrideObject2.kt index 38360355781..9646e9e2740 100644 --- a/j2k/tests/testData/ast/function/overrideObject2.kt +++ b/j2k/tests/testData/ast/function/overrideObject2.kt @@ -5,7 +5,7 @@ class X() : Base() { return super.hashCode() } - override fun equals(other: Any?): Boolean { + override fun equals(o: Any?): Boolean { return super.equals(o) } @@ -13,6 +13,7 @@ class X() : Base() { return super.toString() } + throws(javaClass()) protected fun clone(): Any { return super.clone() } diff --git a/j2k/tests/testData/ast/function/overrideObject3.java.todo b/j2k/tests/testData/ast/function/overrideObject3.java similarity index 100% rename from j2k/tests/testData/ast/function/overrideObject3.java.todo rename to j2k/tests/testData/ast/function/overrideObject3.java diff --git a/j2k/tests/testData/ast/function/overrideObject3.kt b/j2k/tests/testData/ast/function/overrideObject3.kt index 94e655b81d6..de83777788d 100644 --- a/j2k/tests/testData/ast/function/overrideObject3.kt +++ b/j2k/tests/testData/ast/function/overrideObject3.kt @@ -1,5 +1,5 @@ class Base() { - override fun equals(other: Any?): Boolean { + override fun equals(o: Any?): Boolean { return super.equals(o) } } diff --git a/j2k/tests/testData/ast/function/throws.java b/j2k/tests/testData/ast/function/throws.java new file mode 100644 index 00000000000..74c4bfea6db --- /dev/null +++ b/j2k/tests/testData/ast/function/throws.java @@ -0,0 +1,2 @@ +//method +void foo() throws IOException, SerializationException; \ No newline at end of file diff --git a/j2k/tests/testData/ast/function/throws.kt b/j2k/tests/testData/ast/function/throws.kt new file mode 100644 index 00000000000..adc20745905 --- /dev/null +++ b/j2k/tests/testData/ast/function/throws.kt @@ -0,0 +1,2 @@ +throws(javaClass(), javaClass()) +fun foo() \ No newline at end of file diff --git a/j2k/tests/testData/ast/inheritance/classOneExtendsBaseGeneric.kt b/j2k/tests/testData/ast/inheritance/classOneExtendsBaseGeneric.kt index 3013c8a3582..d4499d9b10c 100644 --- a/j2k/tests/testData/ast/inheritance/classOneExtendsBaseGeneric.kt +++ b/j2k/tests/testData/ast/inheritance/classOneExtendsBaseGeneric.kt @@ -1,3 +1,3 @@ class Base(name: T) -class One(name: T, private var mySecond: K) : Base(name) \ No newline at end of file +class One(name: T, private val mySecond: K) : Base(name) \ No newline at end of file diff --git a/j2k/tests/testData/ast/inheritance/classOneExtendsBaseWithZeroParamsNonEmptyConstructor.kt b/j2k/tests/testData/ast/inheritance/classOneExtendsBaseWithZeroParamsNonEmptyConstructor.kt index 800d1f056c8..89d621b7bbf 100644 --- a/j2k/tests/testData/ast/inheritance/classOneExtendsBaseWithZeroParamsNonEmptyConstructor.kt +++ b/j2k/tests/testData/ast/inheritance/classOneExtendsBaseWithZeroParamsNonEmptyConstructor.kt @@ -1,3 +1,3 @@ class Base(name: String) -class One(name: String, private var mySecond: String) : Base(name) \ No newline at end of file +class One(name: String, private val mySecond: String) : Base(name) \ No newline at end of file diff --git a/j2k/tests/testData/ast/issues/comments.kt b/j2k/tests/testData/ast/issues/comments.kt index fc29fd34d76..9ccc6394f66 100644 --- a/j2k/tests/testData/ast/issues/comments.kt +++ b/j2k/tests/testData/ast/issues/comments.kt @@ -15,7 +15,7 @@ class C() { /** * This is a field doc comment. */ - private var i: Int = 0 + private val i: Int = 0 /** * This is a function doc comment. diff --git a/j2k/tests/testData/ast/issues/doNotQualifyStatic.java b/j2k/tests/testData/ast/issues/doNotQualifyStatic.java new file mode 100644 index 00000000000..21c3eddb23c --- /dev/null +++ b/j2k/tests/testData/ast/issues/doNotQualifyStatic.java @@ -0,0 +1,10 @@ +//file +class Outer { + public static Object o = new Object(); + + public static class Nested { + public void foo() { + o = null; + } + } +} diff --git a/j2k/tests/testData/ast/issues/doNotQualifyStatic.kt b/j2k/tests/testData/ast/issues/doNotQualifyStatic.kt new file mode 100644 index 00000000000..d9e1d59ea45 --- /dev/null +++ b/j2k/tests/testData/ast/issues/doNotQualifyStatic.kt @@ -0,0 +1,12 @@ +class Outer() { + + public class Nested() { + public fun foo() { + o = null + } + } + + class object { + public var o: Any? = Object() + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/issues/kt-638.kt b/j2k/tests/testData/ast/issues/kt-638.kt index 5e8777317de..6e7be82d223 100644 --- a/j2k/tests/testData/ast/issues/kt-638.kt +++ b/j2k/tests/testData/ast/issues/kt-638.kt @@ -1,5 +1,5 @@ -public class Identifier private(private val myName: T, private var myHasDollar: Boolean) { - private var myNullable: Boolean = true +public class Identifier private(private val myName: T, private val myHasDollar: Boolean) { + private var myNullable = true public fun getName(): T { return myName @@ -7,18 +7,18 @@ public class Identifier private(private val myName: T, private var myHasDolla class object { - public fun init(name: T): Identifier { + public fun create(name: T): Identifier { val __ = Identifier(name, false) return __ } - public fun init(name: T, isNullable: Boolean): Identifier { + public fun create(name: T, isNullable: Boolean): Identifier { val __ = Identifier(name, false) __.myNullable = isNullable return __ } - public fun init(name: T, hasDollar: Boolean, isNullable: Boolean): Identifier { + public fun create(name: T, hasDollar: Boolean, isNullable: Boolean): Identifier { val __ = Identifier(name, hasDollar) __.myNullable = isNullable return __ @@ -29,9 +29,9 @@ public class Identifier private(private val myName: T, private var myHasDolla public class User() { class object { public fun main(args: Array) { - val i1 = Identifier.init("name", false, true) - val i2 = Identifier.init("name", false) - val i3 = Identifier.init("name") + val i1 = Identifier.create("name", false, true) + val i2 = Identifier.create("name", false) + val i3 = Identifier.create("name") } } } diff --git a/j2k/tests/testData/ast/issues/kt-696.kt b/j2k/tests/testData/ast/issues/kt-696.kt index 405b1c9e5d3..d9aefd9c3ac 100644 --- a/j2k/tests/testData/ast/issues/kt-696.kt +++ b/j2k/tests/testData/ast/issues/kt-696.kt @@ -5,7 +5,7 @@ class Base() { return super.hashCode() } - override fun equals(other: Any?): Boolean { + override fun equals(o: Any?): Boolean { return super.equals(o) } @@ -19,7 +19,7 @@ class Child() : Base() { return super.hashCode() } - override fun equals(o: Any): Boolean { + override fun equals(o: Any?): Boolean { return super.equals(o) } diff --git a/j2k/tests/testData/ast/issues/kt-809-string.kt b/j2k/tests/testData/ast/issues/kt-809-string.kt index 5a4bed58e1f..b6e142a9f62 100644 --- a/j2k/tests/testData/ast/issues/kt-809-string.kt +++ b/j2k/tests/testData/ast/issues/kt-809-string.kt @@ -1,12 +1,12 @@ package demo class Container() { - var myString: String = "1" + var myString = "1" } class One() { class object { - var myContainer: Container = Container() + var myContainer = Container() } } diff --git a/j2k/tests/testData/ast/issues/kt-809.kt b/j2k/tests/testData/ast/issues/kt-809.kt index 07d1c14aad1..c5f8865c31c 100644 --- a/j2k/tests/testData/ast/issues/kt-809.kt +++ b/j2k/tests/testData/ast/issues/kt-809.kt @@ -1,12 +1,12 @@ package demo class Container() { - var myInt: Int = 1 + var myInt = 1 } class One() { class object { - var myContainer: Container = Container() + var myContainer = Container() } } diff --git a/j2k/tests/testData/ast/issues/kt-820-field.kt b/j2k/tests/testData/ast/issues/kt-820-field.kt index 83bc0ee2951..897f1a2ce91 100644 --- a/j2k/tests/testData/ast/issues/kt-820-field.kt +++ b/j2k/tests/testData/ast/issues/kt-820-field.kt @@ -1,12 +1,12 @@ package demo class Container() { - var myInt: Int = 1 + var myInt = 1 } class One() { class object { - var myContainer: Container = Container() + var myContainer = Container() } } diff --git a/j2k/tests/testData/ast/issues/kt-820.kt b/j2k/tests/testData/ast/issues/kt-820.kt index e654ea3b795..fc630979d15 100644 --- a/j2k/tests/testData/ast/issues/kt-820.kt +++ b/j2k/tests/testData/ast/issues/kt-820.kt @@ -1,12 +1,12 @@ package demo class Container() { - var myInt: Int = 1 + var myInt = 1 } class One() { class object { - var myContainer: Container = Container() + var myContainer = Container() } } diff --git a/j2k/tests/testData/ast/issues/kt-824-isDir.kt b/j2k/tests/testData/ast/issues/kt-824-isDir.kt index a723949070d..a02066bb927 100644 --- a/j2k/tests/testData/ast/issues/kt-824-isDir.kt +++ b/j2k/tests/testData/ast/issues/kt-824-isDir.kt @@ -8,11 +8,11 @@ import java.io.File public class Test() { class object { public fun isDir(parent: File?): Boolean { - if (parent == null || !parent?.exists()!!) { + if (parent == null || !parent!!.exists()) { return false } val result = true - if (parent?.isDirectory()!!) { + if (parent!!.isDirectory()) { return true } else return false diff --git a/j2k/tests/testData/ast/issues/kt-824.kt b/j2k/tests/testData/ast/issues/kt-824.kt index 564d50a4afd..d7d016b07b8 100644 --- a/j2k/tests/testData/ast/issues/kt-824.kt +++ b/j2k/tests/testData/ast/issues/kt-824.kt @@ -1,12 +1,12 @@ package demo class Container() { - var myBoolean: Boolean = true + var myBoolean = true } class One() { class object { - var myContainer: Container = Container() + var myContainer = Container() } } diff --git a/j2k/tests/testData/ast/issues/kt-836.kt b/j2k/tests/testData/ast/issues/kt-836.kt index e1799b31b15..1737733743c 100644 --- a/j2k/tests/testData/ast/issues/kt-836.kt +++ b/j2k/tests/testData/ast/issues/kt-836.kt @@ -9,7 +9,6 @@ public class Language(protected var code: String) : Serializable { } } - class Base() { fun test() { } diff --git a/j2k/tests/testData/ast/issues/kt-837.kt b/j2k/tests/testData/ast/issues/kt-837.kt index 587bc252bcc..b6b3bef0653 100644 --- a/j2k/tests/testData/ast/issues/kt-837.kt +++ b/j2k/tests/testData/ast/issues/kt-837.kt @@ -11,7 +11,6 @@ public class Language(protected var code: String) : Serializable { class object { public var ENGLISH: Language = Language("en") public var SWEDISH: Language = Language("sv") - - private val serialVersionUID: Long = -2442762969929206780 + private val serialVersionUID = -2442762969929206780 } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/issues/kt-963.kt b/j2k/tests/testData/ast/issues/kt-963.kt index b3a33d854cd..e2ec0dd01ab 100644 --- a/j2k/tests/testData/ast/issues/kt-963.kt +++ b/j2k/tests/testData/ast/issues/kt-963.kt @@ -1,7 +1,7 @@ package demo class C(a: Int) { - var abc: Int = 0 + var abc = 0 { abc = a * 2 diff --git a/j2k/tests/testData/ast/issues/spaceBeforeAssignment.java b/j2k/tests/testData/ast/issues/spaceBeforeAssignment.java new file mode 100644 index 00000000000..fc6916bfbb3 --- /dev/null +++ b/j2k/tests/testData/ast/issues/spaceBeforeAssignment.java @@ -0,0 +1,6 @@ +//file +import java.util.* + +class A { + List list = new ArrayList(); +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/issues/spaceBeforeAssignment.kt b/j2k/tests/testData/ast/issues/spaceBeforeAssignment.kt new file mode 100644 index 00000000000..7f360fb4f0d --- /dev/null +++ b/j2k/tests/testData/ast/issues/spaceBeforeAssignment.kt @@ -0,0 +1,6 @@ +import java.util.* +import kotlin.List + +class A() { + var list: List = ArrayList() +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/kotlinApiAccess/CorrectFunNullabilityDetected.kt b/j2k/tests/testData/ast/kotlinApiAccess/CorrectFunNullabilityDetected.kt index 636dbbc12e0..fc60f982b07 100644 --- a/j2k/tests/testData/ast/kotlinApiAccess/CorrectFunNullabilityDetected.kt +++ b/j2k/tests/testData/ast/kotlinApiAccess/CorrectFunNullabilityDetected.kt @@ -2,6 +2,6 @@ import kotlinApi.* class A() { fun foo(t: KotlinTrait): Int { - return t.nullableFun()?.length()!! + t.notNullableFun().length() + return t.nullableFun()!!.length() + t.notNullableFun().length() } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/kotlinApiAccess/CorrectNullabilityDetected.kt b/j2k/tests/testData/ast/kotlinApiAccess/CorrectNullabilityDetected.kt index c6e87d24074..5f0a497b350 100644 --- a/j2k/tests/testData/ast/kotlinApiAccess/CorrectNullabilityDetected.kt +++ b/j2k/tests/testData/ast/kotlinApiAccess/CorrectNullabilityDetected.kt @@ -2,6 +2,6 @@ import kotlinApi.* class A() { fun foo(c: KotlinClass): Int { - return c.nullableProperty?.length()!! + c.property.length() + KotlinClass.nullableStaticVar!! + KotlinClass.staticVar + KotlinClass.nullableStaticFun(1)!! + KotlinClass.staticFun(1) + nullableGlobalFunction("")?.length()!! + globalFunction("").length() + return c.nullableProperty!!.length() + c.property.length() + KotlinClass.nullableStaticVar!! + KotlinClass.staticVar + KotlinClass.nullableStaticFun(1)!! + KotlinClass.staticFun(1) + nullableGlobalFunction("")!!.length() + globalFunction("").length() } } \ No newline at end of file diff --git a/j2k/tests/testData/ast/kotlinExclusion/kt-656.kt b/j2k/tests/testData/ast/kotlinExclusion/kt-656.kt deleted file mode 100644 index c937addb228..00000000000 --- a/j2k/tests/testData/ast/kotlinExclusion/kt-656.kt +++ /dev/null @@ -1,23 +0,0 @@ -package demo - -class Test() : java.lang.Iterable { - override fun iterator(): java.util.Iterator? { - return null - } - - public fun push(i: java.util.Iterator): java.util.Iterator { - val j = i - return j - } -} - -class FullTest() : java.lang.Iterable { - override fun iterator(): java.util.Iterator? { - return null - } - - public fun push(i: java.util.Iterator): java.util.Iterator { - val j = i - return j - } -} \ No newline at end of file diff --git a/j2k/tests/testData/ast/newClassExpression/newClassWithAnonymousScope.java b/j2k/tests/testData/ast/newClassExpression/newAnonymousClass.java similarity index 100% rename from j2k/tests/testData/ast/newClassExpression/newClassWithAnonymousScope.java rename to j2k/tests/testData/ast/newClassExpression/newAnonymousClass.java diff --git a/j2k/tests/testData/ast/newClassExpression/newClassWithAnonymousScope.kt b/j2k/tests/testData/ast/newClassExpression/newAnonymousClass.kt similarity index 75% rename from j2k/tests/testData/ast/newClassExpression/newClassWithAnonymousScope.kt rename to j2k/tests/testData/ast/newClassExpression/newAnonymousClass.kt index 7c22181b2aa..da09fb6ea84 100644 --- a/j2k/tests/testData/ast/newClassExpression/newClassWithAnonymousScope.kt +++ b/j2k/tests/testData/ast/newClassExpression/newAnonymousClass.kt @@ -1,4 +1,4 @@ -object : Runnable() { +object : Runnable { override fun run() { System.out.println("Run") } diff --git a/j2k/tests/testData/ast/newClassExpression/newAnonymousClass2.java b/j2k/tests/testData/ast/newClassExpression/newAnonymousClass2.java new file mode 100644 index 00000000000..dc732c71ca6 --- /dev/null +++ b/j2k/tests/testData/ast/newClassExpression/newAnonymousClass2.java @@ -0,0 +1,13 @@ +//file +abstract class A {} + +class C { + void foo() { + A a = new A() { + @Override + public String toString() { + return "a"; + } + }; + } +} diff --git a/j2k/tests/testData/ast/newClassExpression/newAnonymousClass2.kt b/j2k/tests/testData/ast/newClassExpression/newAnonymousClass2.kt new file mode 100644 index 00000000000..e8d2763a65a --- /dev/null +++ b/j2k/tests/testData/ast/newClassExpression/newAnonymousClass2.kt @@ -0,0 +1,11 @@ +abstract class A() + +class C() { + fun foo() { + val a = object : A() { + override fun toString(): String { + return "a" + } + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/newClassExpression/newAnonymousClass3.java b/j2k/tests/testData/ast/newClassExpression/newAnonymousClass3.java new file mode 100644 index 00000000000..34283df60aa --- /dev/null +++ b/j2k/tests/testData/ast/newClassExpression/newAnonymousClass3.java @@ -0,0 +1,27 @@ +//file +import kotlinApi.KotlinTrait; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +class C { + void foo() { + KotlinTrait t = new KotlinTrait() { + @Nullable + @Override + public String nullableFun() { + return null; + } + + @NotNull + @Override + public String notNullableFun() { + return ""; + } + + @Override + public int nonAbstractFun() { + return 0; + } + }; + } +} diff --git a/j2k/tests/testData/ast/newClassExpression/newAnonymousClass3.kt b/j2k/tests/testData/ast/newClassExpression/newAnonymousClass3.kt new file mode 100644 index 00000000000..bd3ffc22d48 --- /dev/null +++ b/j2k/tests/testData/ast/newClassExpression/newAnonymousClass3.kt @@ -0,0 +1,19 @@ +import kotlinApi.KotlinTrait + +class C() { + fun foo() { + val t = object : KotlinTrait { + override fun nullableFun(): String? { + return null + } + + override fun notNullableFun(): String { + return "" + } + + override fun nonAbstractFun(): Int { + return 0 + } + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/newClassExpression/newInnerClass.kt b/j2k/tests/testData/ast/newClassExpression/newInnerClass.kt index 48064b3ce9f..e7d3a2927cf 100644 --- a/j2k/tests/testData/ast/newClassExpression/newInnerClass.kt +++ b/j2k/tests/testData/ast/newClassExpression/newInnerClass.kt @@ -1,7 +1,7 @@ package org.test class OuterClass() { - class InnerClass() + inner class InnerClass() } class User() { diff --git a/j2k/tests/testData/ast/newClassExpression/newStaticInnerClass.kt b/j2k/tests/testData/ast/newClassExpression/newStaticInnerClass.kt index 5dea1cbe8f3..f55170cf603 100644 --- a/j2k/tests/testData/ast/newClassExpression/newStaticInnerClass.kt +++ b/j2k/tests/testData/ast/newClassExpression/newStaticInnerClass.kt @@ -1,9 +1,7 @@ package demo class Foo() { - class object { - class Bar() - } + class Bar() } class User() { diff --git a/j2k/tests/testData/ast/nullability/FieldComparedWithNull.kt b/j2k/tests/testData/ast/nullability/FieldComparedWithNull.kt index 7b8d014387f..f959711ac1e 100644 --- a/j2k/tests/testData/ast/nullability/FieldComparedWithNull.kt +++ b/j2k/tests/testData/ast/nullability/FieldComparedWithNull.kt @@ -1,5 +1,5 @@ class C() { - private var s: String? = x() + private val s = x() fun foo() { if (s == null) { diff --git a/j2k/tests/testData/ast/nullability/FieldComparedWithNull2.kt b/j2k/tests/testData/ast/nullability/FieldComparedWithNull2.kt index 9b5e3dc0528..0d5c31887dc 100644 --- a/j2k/tests/testData/ast/nullability/FieldComparedWithNull2.kt +++ b/j2k/tests/testData/ast/nullability/FieldComparedWithNull2.kt @@ -1,4 +1,4 @@ -class C(private var s: String?) { +class C(private val s: String?) { fun foo() { if (s != null) { diff --git a/j2k/tests/testData/ast/nullability/FieldComparedWithNull4.kt b/j2k/tests/testData/ast/nullability/FieldComparedWithNull4.kt index 95ca8178272..54fad2fe62c 100644 --- a/j2k/tests/testData/ast/nullability/FieldComparedWithNull4.kt +++ b/j2k/tests/testData/ast/nullability/FieldComparedWithNull4.kt @@ -1,4 +1,4 @@ -class C(private var s: String?) { +class C(private val s: String?) { { if (s == null) { System.out.print("null") diff --git a/j2k/tests/testData/ast/nullability/IndirectOverride.java b/j2k/tests/testData/ast/nullability/IndirectOverride.java new file mode 100644 index 00000000000..6548af24619 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/IndirectOverride.java @@ -0,0 +1,4 @@ +//file +class C extends javaApi.Derived { + public String foo(String s) { return s; } +} diff --git a/j2k/tests/testData/ast/nullability/IndirectOverride.kt b/j2k/tests/testData/ast/nullability/IndirectOverride.kt new file mode 100644 index 00000000000..d65becf9df5 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/IndirectOverride.kt @@ -0,0 +1,5 @@ +class C() : javaApi.Derived() { + override fun foo(s: String?): String? { + return s + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/MethodResultInitializesNullableField.kt b/j2k/tests/testData/ast/nullability/MethodResultInitializesNullableField.kt index 3bde9e28c4b..de5326c20b9 100644 --- a/j2k/tests/testData/ast/nullability/MethodResultInitializesNullableField.kt +++ b/j2k/tests/testData/ast/nullability/MethodResultInitializesNullableField.kt @@ -1,5 +1,5 @@ class C() { - private val string: String? = getString() + private val string = getString() class object { diff --git a/j2k/tests/testData/ast/nullability/MethodReturnsNullInAnonymousClass.kt b/j2k/tests/testData/ast/nullability/MethodReturnsNullInAnonymousClass.kt index 9dd3ed82b41..b3b27e608e2 100644 --- a/j2k/tests/testData/ast/nullability/MethodReturnsNullInAnonymousClass.kt +++ b/j2k/tests/testData/ast/nullability/MethodReturnsNullInAnonymousClass.kt @@ -4,7 +4,7 @@ trait Getter { class C() { fun foo(b: Boolean): String { - val getter = object : Getter() { + val getter = object : Getter { override fun get(): String? { return null } diff --git a/j2k/tests/testData/ast/nullability/NullableIntNoCrash.java b/j2k/tests/testData/ast/nullability/NullableIntNoCrash.java new file mode 100644 index 00000000000..ba4276df19f --- /dev/null +++ b/j2k/tests/testData/ast/nullability/NullableIntNoCrash.java @@ -0,0 +1,8 @@ +import org.jetbrains.annotations.Nullable; + +//file +class A { + int field = foo(); + + @Nullable int foo() { return 1; } +} diff --git a/j2k/tests/testData/ast/nullability/NullableIntNoCrash.kt b/j2k/tests/testData/ast/nullability/NullableIntNoCrash.kt new file mode 100644 index 00000000000..83dda3a4ae5 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/NullableIntNoCrash.kt @@ -0,0 +1,7 @@ +class A() { + var field = foo() + + fun foo(): Int { + return 1 + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/NullableMethodDotAccess.kt b/j2k/tests/testData/ast/nullability/NullableMethodDotAccess.kt index efc5e709736..4bef51b9f32 100644 --- a/j2k/tests/testData/ast/nullability/NullableMethodDotAccess.kt +++ b/j2k/tests/testData/ast/nullability/NullableMethodDotAccess.kt @@ -4,6 +4,6 @@ class C() { } fun foo(): Int { - return getString(true)?.length()!! + return getString(true)!!.length() } -} \ No newline at end of file +} diff --git a/j2k/tests/testData/ast/nullability/NullableVariableDotAccess.kt b/j2k/tests/testData/ast/nullability/NullableVariableDotAccess.kt index 93b77147fd1..01480307817 100644 --- a/j2k/tests/testData/ast/nullability/NullableVariableDotAccess.kt +++ b/j2k/tests/testData/ast/nullability/NullableVariableDotAccess.kt @@ -1,5 +1,5 @@ fun foo(s: String?, b: Boolean): Int { if (s == null) System.out.println("null") - if (b) return s?.length()!! + if (b) return s!!.length() return 10 } \ No newline at end of file diff --git a/j2k/tests/testData/ast/nullability/OverrideWithInheritanceLoop.java b/j2k/tests/testData/ast/nullability/OverrideWithInheritanceLoop.java new file mode 100644 index 00000000000..0d9ca83749c --- /dev/null +++ b/j2k/tests/testData/ast/nullability/OverrideWithInheritanceLoop.java @@ -0,0 +1,8 @@ +//file +class A extends B { + public void foo(String s) {} +} + +class B extends A { + public void foo(String s) {} +} diff --git a/j2k/tests/testData/ast/nullability/OverrideWithInheritanceLoop.kt b/j2k/tests/testData/ast/nullability/OverrideWithInheritanceLoop.kt new file mode 100644 index 00000000000..b4577d0e5d0 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/OverrideWithInheritanceLoop.kt @@ -0,0 +1,9 @@ +class A() : B() { + public fun foo(s: String) { + } +} + +class B() : A() { + public fun foo(s: String) { + } +} diff --git a/j2k/tests/testData/ast/nullability/Overrides.java b/j2k/tests/testData/ast/nullability/Overrides.java new file mode 100644 index 00000000000..93a02f5450b --- /dev/null +++ b/j2k/tests/testData/ast/nullability/Overrides.java @@ -0,0 +1,26 @@ +//file +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +class Base { + @Nullable + public String foo(@Nullable String s) { return ""; } + + public String bar(String s) { + return s != null ? s + 1 : null; + } + + public String zoo(Object o){ return ""; } +} + +interface I { + @Nullable String zoo(@Nullable Object o); +} + +class C extends Base implements I { + public String foo(String s) { return ""; } + + public String bar(String s) { return ""; } + + public String zoo(Object o) { return ""; } +} diff --git a/j2k/tests/testData/ast/nullability/Overrides.kt b/j2k/tests/testData/ast/nullability/Overrides.kt new file mode 100644 index 00000000000..0158b9f0f68 --- /dev/null +++ b/j2k/tests/testData/ast/nullability/Overrides.kt @@ -0,0 +1,31 @@ +class Base() { + public fun foo(s: String?): String? { + return "" + } + + public fun bar(s: String?): String? { + return if (s != null) s + 1 else null + } + + public fun zoo(o: Any): String { + return "" + } +} + +trait I { + public fun zoo(o: Any?): String? +} + +class C() : Base(), I { + override fun foo(s: String?): String? { + return "" + } + + override fun bar(s: String?): String? { + return "" + } + + override fun zoo(o: Any?): String? { + return "" + } +} diff --git a/j2k/tests/testData/ast/prefixOperator/nullableIf.kt b/j2k/tests/testData/ast/prefixOperator/nullableIf.kt index 209e96d341b..d294f76c13d 100644 --- a/j2k/tests/testData/ast/prefixOperator/nullableIf.kt +++ b/j2k/tests/testData/ast/prefixOperator/nullableIf.kt @@ -1,3 +1,3 @@ val s = null -if (!s?.isEmpty()!!) { +if (!s!!.isEmpty()) { } \ No newline at end of file diff --git a/j2k/tests/testData/ast/returnStatement/currentMethodBug.java b/j2k/tests/testData/ast/returnStatement/currentMethodBug.java new file mode 100644 index 00000000000..688643d3a5d --- /dev/null +++ b/j2k/tests/testData/ast/returnStatement/currentMethodBug.java @@ -0,0 +1,22 @@ +//file +import org.jetbrains.annotations.Nullable; + +interface I { + int getInt(); +} + +class C { + @Nullable Object getObject() { + foo(new I() { + @Override + public int getInt() { + return 0; + } + }); + return string; + } + + void foo(I i) {} + + @Nullable String string; +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/returnStatement/currentMethodBug.kt b/j2k/tests/testData/ast/returnStatement/currentMethodBug.kt new file mode 100644 index 00000000000..1b5e724938a --- /dev/null +++ b/j2k/tests/testData/ast/returnStatement/currentMethodBug.kt @@ -0,0 +1,19 @@ +trait I { + public fun getInt(): Int +} + +class C() { + fun getObject(): Any? { + foo(object : I { + override fun getInt(): Int { + return 0 + } + }) + return string + } + + fun foo(i: I) { + } + + var string: String? = null +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/settings/specifyFieldTypeByDefault.java b/j2k/tests/testData/ast/settings/specifyFieldTypeByDefault.java new file mode 100644 index 00000000000..e8bf96c57d5 --- /dev/null +++ b/j2k/tests/testData/ast/settings/specifyFieldTypeByDefault.java @@ -0,0 +1,11 @@ +//file +// !specifyFieldTypeByDefault: true +import org.jetbrains.annotations.Nullable; +import java.util.*; + +class A { + private final List field1 = new ArrayList(); + final List field2 = new ArrayList(); + public final int field3 = 0; + protected final int field4 = 0; +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/settings/specifyFieldTypeByDefault.kt b/j2k/tests/testData/ast/settings/specifyFieldTypeByDefault.kt new file mode 100644 index 00000000000..72942153033 --- /dev/null +++ b/j2k/tests/testData/ast/settings/specifyFieldTypeByDefault.kt @@ -0,0 +1,10 @@ +// !specifyFieldTypeByDefault: true +import java.util.* +import kotlin.List + +class A() { + private val field1: List = ArrayList() + val field2: List = ArrayList() + public val field3: Int = 0 + protected val field4: Int = 0 +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/staticMembers/PrivateStaticMembers.java b/j2k/tests/testData/ast/staticMembers/PrivateStaticMembers.java new file mode 100644 index 00000000000..498381b2684 --- /dev/null +++ b/j2k/tests/testData/ast/staticMembers/PrivateStaticMembers.java @@ -0,0 +1,12 @@ +//file +class A { + private static final String s = "abc"; + + public void foo() { + privateStatic1(); + privateStatic2(); + } + + private static void privateStatic1(){} + private static void privateStatic2(){} +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/staticMembers/PrivateStaticMembers.kt b/j2k/tests/testData/ast/staticMembers/PrivateStaticMembers.kt new file mode 100644 index 00000000000..b44c55a1b3e --- /dev/null +++ b/j2k/tests/testData/ast/staticMembers/PrivateStaticMembers.kt @@ -0,0 +1,16 @@ +class A() { + + public fun foo() { + privateStatic1() + privateStatic2() + } + + class object { + private val s = "abc" + + private fun privateStatic1() { + } + private fun privateStatic2() { + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods1.java b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods1.java new file mode 100644 index 00000000000..9768e323943 --- /dev/null +++ b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods1.java @@ -0,0 +1,10 @@ +//file +class A { + public void foo() { + privateStatic1(); + privateStatic2(); + } + + private static void privateStatic1(){} + private static void privateStatic2(){} +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods1.kt b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods1.kt new file mode 100644 index 00000000000..229e28304da --- /dev/null +++ b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods1.kt @@ -0,0 +1,11 @@ +class A() { + public fun foo() { + privateStatic1() + privateStatic2() + } + + private fun privateStatic1() { + } + private fun privateStatic2() { + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods2.java b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods2.java new file mode 100644 index 00000000000..5b0423188fd --- /dev/null +++ b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods2.java @@ -0,0 +1,14 @@ +//file +class A { + public void foo() { + privateStatic1(); + privateStatic2(); + } + + public static void publicStatic(){ + privateStatic1(); + } + + private static void privateStatic1(){} + private static void privateStatic2(){} +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods2.kt b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods2.kt new file mode 100644 index 00000000000..3b82bb877b5 --- /dev/null +++ b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods2.kt @@ -0,0 +1,18 @@ +class A() { + public fun foo() { + privateStatic1() + privateStatic2() + } + + class object { + + public fun publicStatic() { + privateStatic1() + } + + private fun privateStatic1() { + } + private fun privateStatic2() { + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods3.java b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods3.java new file mode 100644 index 00000000000..126fea3b83b --- /dev/null +++ b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods3.java @@ -0,0 +1,15 @@ +//file +class A { + public static class Nested { + void foo() { + privateStatic1(); + } + } + + void bar() { + privateStatic2(); + } + + private static void privateStatic1(){} + private static void privateStatic2(){} +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods3.kt b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods3.kt new file mode 100644 index 00000000000..6790b6973dd --- /dev/null +++ b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods3.kt @@ -0,0 +1,19 @@ +class A() { + public class Nested() { + fun foo() { + privateStatic1() + } + } + + fun bar() { + privateStatic2() + } + + class object { + + private fun privateStatic1() { + } + private fun privateStatic2() { + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods4.java b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods4.java new file mode 100644 index 00000000000..b0696b6fa61 --- /dev/null +++ b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods4.java @@ -0,0 +1,15 @@ +//file +class A { + public class Inner { + void foo() { + privateStatic1(); + } + } + + void bar() { + privateStatic2(); + } + + private static void privateStatic1(){} + private static void privateStatic2(){} +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods4.kt b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods4.kt new file mode 100644 index 00000000000..31929271185 --- /dev/null +++ b/j2k/tests/testData/ast/staticMembers/PrivateStaticMethods4.kt @@ -0,0 +1,16 @@ +class A() { + public inner class Inner() { + fun foo() { + privateStatic1() + } + } + + fun bar() { + privateStatic2() + } + + private fun privateStatic1() { + } + private fun privateStatic2() { + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/superExpression/classAdotSuperFoo.java b/j2k/tests/testData/ast/superExpression/classAdotSuperFoo.java index 2f5f53113af..33cea2861b2 100644 --- a/j2k/tests/testData/ast/superExpression/classAdotSuperFoo.java +++ b/j2k/tests/testData/ast/superExpression/classAdotSuperFoo.java @@ -1,4 +1,6 @@ //file +package a.b; + class Base { void foo(); } diff --git a/j2k/tests/testData/ast/superExpression/classAdotSuperFoo.kt b/j2k/tests/testData/ast/superExpression/classAdotSuperFoo.kt index 3ed8769e54b..1585ecae8d1 100644 --- a/j2k/tests/testData/ast/superExpression/classAdotSuperFoo.kt +++ b/j2k/tests/testData/ast/superExpression/classAdotSuperFoo.kt @@ -1,9 +1,11 @@ +package a.b + class Base() { fun foo() } class A() : Base() { - class C() { + inner class C() { fun test() { super@A.foo() } diff --git a/j2k/tests/testData/ast/thisExpression/classAdotThisFoo.java b/j2k/tests/testData/ast/thisExpression/classAdotThisFoo.java index 0d2259d6e9b..fa564c172e7 100644 --- a/j2k/tests/testData/ast/thisExpression/classAdotThisFoo.java +++ b/j2k/tests/testData/ast/thisExpression/classAdotThisFoo.java @@ -1,4 +1,6 @@ //file +package a.b + class Base { void foo() {} } diff --git a/j2k/tests/testData/ast/thisExpression/classAdotThisFoo.kt b/j2k/tests/testData/ast/thisExpression/classAdotThisFoo.kt index 9cd50bbe58d..f32bed7d370 100644 --- a/j2k/tests/testData/ast/thisExpression/classAdotThisFoo.kt +++ b/j2k/tests/testData/ast/thisExpression/classAdotThisFoo.kt @@ -1,10 +1,12 @@ +package a.b + class Base() { fun foo() { } } class A() : Base() { - class C() { + inner class C() { fun test() { this@A.foo() } diff --git a/j2k/tests/testData/ast/toKotlinClasses/TypeParameterBound.java b/j2k/tests/testData/ast/toKotlinClasses/TypeParameterBound.java new file mode 100644 index 00000000000..ab21c84b55a --- /dev/null +++ b/j2k/tests/testData/ast/toKotlinClasses/TypeParameterBound.java @@ -0,0 +1,8 @@ +//file +import java.util.*; + +interface I>> { +} + +class C implements I>> { +} diff --git a/j2k/tests/testData/ast/toKotlinClasses/TypeParameterBound.kt b/j2k/tests/testData/ast/toKotlinClasses/TypeParameterBound.kt new file mode 100644 index 00000000000..f385c2f6829 --- /dev/null +++ b/j2k/tests/testData/ast/toKotlinClasses/TypeParameterBound.kt @@ -0,0 +1,7 @@ +import java.util.* +import kotlin.List +import kotlin.Iterator + +trait I>> + +class C() : I>> diff --git a/j2k/tests/testData/ast/kotlinExclusion/kt-656.java b/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator.java similarity index 100% rename from j2k/tests/testData/ast/kotlinExclusion/kt-656.java rename to j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator.java diff --git a/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator.kt b/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator.kt new file mode 100644 index 00000000000..97687578f5e --- /dev/null +++ b/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator.kt @@ -0,0 +1,23 @@ +package demo + +class Test() : Iterable { + override fun iterator(): Iterator? { + return null + } + + public fun push(i: Iterator): Iterator { + val j = i + return j + } +} + +class FullTest() : Iterable { + override fun iterator(): Iterator? { + return null + } + + public fun push(i: Iterator): Iterator { + val j = i + return j + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator2.java b/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator2.java new file mode 100644 index 00000000000..4edc5a4835c --- /dev/null +++ b/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator2.java @@ -0,0 +1,28 @@ +//file +package demo; + +import java.util.*; + +class Test implements Iterable { + @Override + public Iterator iterator() { + return null; + } + + public Iterator push(Iterator i) { + Iterator j = i; + return j; + } +} + +class FullTest implements java.lang.Iterable { + @Override + public java.util.Iterator iterator() { + return null; + } + + public java.util.Iterator push(java.util.Iterator i) { + java.util.Iterator j = i; + return j; + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator2.kt b/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator2.kt new file mode 100644 index 00000000000..868627c5061 --- /dev/null +++ b/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator2.kt @@ -0,0 +1,26 @@ +package demo + +import java.util.* +import kotlin.Iterator + +class Test() : Iterable { + override fun iterator(): Iterator? { + return null + } + + public fun push(i: Iterator): Iterator { + val j = i + return j + } +} + +class FullTest() : Iterable { + override fun iterator(): Iterator? { + return null + } + + public fun push(i: Iterator): Iterator { + val j = i + return j + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator3.java b/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator3.java new file mode 100644 index 00000000000..b6651131a14 --- /dev/null +++ b/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator3.java @@ -0,0 +1,16 @@ +//file +package demo; + +import java.util.Iterator; + +class Test implements Iterable { + @Override + public Iterator iterator() { + return null; + } + + public Iterator push(Iterator i) { + Iterator j = i; + return j; + } +} diff --git a/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator3.kt b/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator3.kt new file mode 100644 index 00000000000..c741d5c583c --- /dev/null +++ b/j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator3.kt @@ -0,0 +1,12 @@ +package demo + +class Test() : Iterable { + override fun iterator(): Iterator? { + return null + } + + public fun push(i: Iterator): Iterator { + val j = i + return j + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/tryWithResource/Multiline.java b/j2k/tests/testData/ast/tryWithResource/Multiline.java new file mode 100644 index 00000000000..4bc2473a748 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/Multiline.java @@ -0,0 +1,12 @@ +//file +import java.io.*; + +public class C { + void foo() throws IOException { + try(InputStream stream = new FileInputStream("foo")) { + // reading something + int c = stream.read(); + System.out.println(c); + } + } +} diff --git a/j2k/tests/testData/ast/tryWithResource/Multiline.kt b/j2k/tests/testData/ast/tryWithResource/Multiline.kt new file mode 100644 index 00000000000..2a9e653db33 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/Multiline.kt @@ -0,0 +1,12 @@ +import java.io.* + +public class C() { + throws(javaClass()) + fun foo() { + FileInputStream("foo").use { stream -> + // reading something + val c = stream.read() + System.out.println(c) + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/tryWithResource/MultipleResources.java b/j2k/tests/testData/ast/tryWithResource/MultipleResources.java new file mode 100644 index 00000000000..f3dc33b5a36 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/MultipleResources.java @@ -0,0 +1,12 @@ +//file +import java.io.*; + +public class C { + void foo() throws IOException { + try(InputStream input = new FileInputStream("foo"); + OutputStream output = new FileOutputStream("bar")) { + output.write(input.read()); + output.write(0); + } + } +} diff --git a/j2k/tests/testData/ast/tryWithResource/MultipleResources.kt b/j2k/tests/testData/ast/tryWithResource/MultipleResources.kt new file mode 100644 index 00000000000..9e4868f4566 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/MultipleResources.kt @@ -0,0 +1,13 @@ +import java.io.* + +public class C() { + throws(javaClass()) + fun foo() { + FileInputStream("foo").use { input -> + FileOutputStream("bar").use { output -> + output.write(input.read()) + output.write(0) + } + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/tryWithResource/Simple.java b/j2k/tests/testData/ast/tryWithResource/Simple.java new file mode 100644 index 00000000000..c07eaf8b42e --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/Simple.java @@ -0,0 +1,10 @@ +//file +import java.io.*; + +public class C { + void foo() throws IOException { + try(InputStream stream = new FileInputStream("foo")) { + System.out.println(stream.read()); + } + } +} diff --git a/j2k/tests/testData/ast/tryWithResource/Simple.kt b/j2k/tests/testData/ast/tryWithResource/Simple.kt new file mode 100644 index 00000000000..40a727ec4c0 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/Simple.kt @@ -0,0 +1,8 @@ +import java.io.* + +public class C() { + throws(javaClass()) + fun foo() { + FileInputStream("foo").use { stream -> System.out.println(stream.read()) } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/tryWithResource/WithCatch.java b/j2k/tests/testData/ast/tryWithResource/WithCatch.java new file mode 100644 index 00000000000..50e2bb22b68 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithCatch.java @@ -0,0 +1,15 @@ +//file +import java.io.*; + +public class C { + void foo() { + try(InputStream stream = new FileInputStream("foo")) { + // reading something + int c = stream.read(); + System.out.println(c); + } + catch (IOException e) { + System.out.println(e); + } + } +} diff --git a/j2k/tests/testData/ast/tryWithResource/WithCatch.kt b/j2k/tests/testData/ast/tryWithResource/WithCatch.kt new file mode 100644 index 00000000000..dbce19f57cf --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithCatch.kt @@ -0,0 +1,16 @@ +import java.io.* + +public class C() { + fun foo() { + try { + FileInputStream("foo").use { stream -> + // reading something + val c = stream.read() + System.out.println(c) + } + } catch (e: IOException) { + System.out.println(e) + } + + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/tryWithResource/WithCatchAndFinally.java b/j2k/tests/testData/ast/tryWithResource/WithCatchAndFinally.java new file mode 100644 index 00000000000..76821717110 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithCatchAndFinally.java @@ -0,0 +1,18 @@ +//file +import java.io.*; + +public class C { + void foo() { + try(InputStream stream = new FileInputStream("foo")) { + // reading something + int c = stream.read(); + System.out.println(c); + } + catch (IOException e) { + System.out.println(e); + } + finally { + System.out.println("Finally!"); + } + } +} diff --git a/j2k/tests/testData/ast/tryWithResource/WithCatchAndFinally.kt b/j2k/tests/testData/ast/tryWithResource/WithCatchAndFinally.kt new file mode 100644 index 00000000000..0f2747e0540 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithCatchAndFinally.kt @@ -0,0 +1,17 @@ +import java.io.* + +public class C() { + fun foo() { + try { + FileInputStream("foo").use { stream -> + // reading something + val c = stream.read() + System.out.println(c) + } + } catch (e: IOException) { + System.out.println(e) + } finally { + System.out.println("Finally!") + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/tryWithResource/WithCatches.java b/j2k/tests/testData/ast/tryWithResource/WithCatches.java new file mode 100644 index 00000000000..91317aa109a --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithCatches.java @@ -0,0 +1,18 @@ +//file +import java.io.*; + +public class C { + void foo() { + try(InputStream stream = new FileInputStream("foo")) { + // reading something + int c = stream.read(); + System.out.println(c); + } + catch (IOException e) { + System.out.println(e); + } + catch (Exception e) { + System.err.println(e); + } + } +} diff --git a/j2k/tests/testData/ast/tryWithResource/WithCatches.kt b/j2k/tests/testData/ast/tryWithResource/WithCatches.kt new file mode 100644 index 00000000000..87634a2cf45 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithCatches.kt @@ -0,0 +1,18 @@ +import java.io.* + +public class C() { + fun foo() { + try { + FileInputStream("foo").use { stream -> + // reading something + val c = stream.read() + System.out.println(c) + } + } catch (e: IOException) { + System.out.println(e) + } catch (e: Exception) { + System.err.println(e) + } + + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/tryWithResource/WithFinally.java b/j2k/tests/testData/ast/tryWithResource/WithFinally.java new file mode 100644 index 00000000000..e6d40d475e1 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithFinally.java @@ -0,0 +1,15 @@ +//file +import java.io.*; + +public class C { + void foo() throws IOException { + try(InputStream stream = new FileInputStream("foo")) { + // reading something + int c = stream.read(); + System.out.println(c); + } + finally { + // dispose something else + } + } +} diff --git a/j2k/tests/testData/ast/tryWithResource/WithFinally.kt b/j2k/tests/testData/ast/tryWithResource/WithFinally.kt new file mode 100644 index 00000000000..79df2e2cd39 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithFinally.kt @@ -0,0 +1,16 @@ +import java.io.* + +public class C() { + throws(javaClass()) + fun foo() { + try { + FileInputStream("foo").use { stream -> + // reading something + val c = stream.read() + System.out.println(c) + } + } finally { + // dispose something else + } + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/tryWithResource/WithReturn.java.todo b/j2k/tests/testData/ast/tryWithResource/WithReturn.java.todo new file mode 100644 index 00000000000..27183fa29bc --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithReturn.java.todo @@ -0,0 +1,17 @@ +//file +import java.io.*; + +public class C { + int foo() { + try(InputStream stream = new FileInputStream("foo")) { + while(true) { + int c = stream.read(); + if (c < 0 || c > 127) return c; + } + } + catch (IOException e) { + System.out.println(e); + return -1; + } + } +} diff --git a/j2k/tests/testData/ast/tryWithResource/WithReturnAtEnd.java b/j2k/tests/testData/ast/tryWithResource/WithReturnAtEnd.java new file mode 100644 index 00000000000..7a9be09c5ea --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithReturnAtEnd.java @@ -0,0 +1,16 @@ +//file +import java.io.*; + +public class C { + int foo() { + try(InputStream stream = new FileInputStream("foo")) { + // reading something + int c = stream.read(); + return c; + } + catch (IOException e) { + System.out.println(e); + return -1; + } + } +} diff --git a/j2k/tests/testData/ast/tryWithResource/WithReturnAtEnd.kt b/j2k/tests/testData/ast/tryWithResource/WithReturnAtEnd.kt new file mode 100644 index 00000000000..f9fdc00d481 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithReturnAtEnd.kt @@ -0,0 +1,17 @@ +import java.io.* + +public class C() { + fun foo(): Int { + try { + return FileInputStream("foo").use { stream -> + // reading something + val c = stream.read() + c + } + } catch (e: IOException) { + System.out.println(e) + return -1 + } + + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass.java b/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass.java new file mode 100644 index 00000000000..9bc3f676075 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass.java @@ -0,0 +1,23 @@ +//file +import java.io.*; + +interface I { + int doIt(InputStream stream) throws IOException; +} + +public class C { + void foo() throws IOException { + try(InputStream stream = new FileInputStream("foo")) { + bar(new I() { + @Override + public int doIt(InputStream stream) throws IOException { + return stream.available(); + } + }, stream); + } + } + + int bar(I i, InputStream stream) throws IOException { + return i.doIt(stream); + } +} diff --git a/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass.kt b/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass.kt new file mode 100644 index 00000000000..304f88ac3af --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass.kt @@ -0,0 +1,25 @@ +import java.io.* + +trait I { + throws(javaClass()) + public fun doIt(stream: InputStream): Int +} + +public class C() { + throws(javaClass()) + fun foo() { + FileInputStream("foo").use { stream -> + bar(object : I { + throws(javaClass()) + override fun doIt(stream: InputStream): Int { + return stream.available() + } + }, stream) + } + } + + throws(javaClass()) + fun bar(i: I, stream: InputStream): Int { + return i.doIt(stream) + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass2.java b/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass2.java new file mode 100644 index 00000000000..4f1e06a7f2a --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass2.java @@ -0,0 +1,23 @@ +//file +import java.io.*; + +interface I { + int doIt(InputStream stream) throws IOException; +} + +public class C { + int foo() throws IOException { + try(InputStream stream = new FileInputStream("foo")) { + return bar(new I() { + @Override + public int doIt(InputStream stream) throws IOException { + return stream.available(); + } + }, stream); + } + } + + int bar(I i, InputStream stream) throws IOException { + return i.doIt(stream); + } +} diff --git a/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass2.kt b/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass2.kt new file mode 100644 index 00000000000..0b06d409b5d --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass2.kt @@ -0,0 +1,25 @@ +import java.io.* + +trait I { + throws(javaClass()) + public fun doIt(stream: InputStream): Int +} + +public class C() { + throws(javaClass()) + fun foo(): Int { + return FileInputStream("foo").use { stream -> + bar(object : I { + throws(javaClass()) + override fun doIt(stream: InputStream): Int { + return stream.available() + } + }, stream) + } + } + + throws(javaClass()) + fun bar(i: I, stream: InputStream): Int { + return i.doIt(stream) + } +} \ No newline at end of file diff --git a/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass3.java.todo b/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass3.java.todo new file mode 100644 index 00000000000..1872fdbede8 --- /dev/null +++ b/j2k/tests/testData/ast/tryWithResource/WithReturnInAnonymousClass3.java.todo @@ -0,0 +1,26 @@ +//file +import java.io.*; + +interface I { + int doIt(InputStream stream) throws IOException; +} + +public class C { + int foo() throws IOException { + try(InputStream stream = new FileInputStream("foo")) { + if (stream.read() >= 0) { + return bar(new I() { + @Override + public int doIt(InputStream stream) throws IOException { + return stream.available(); + } + }, stream); + } + } + return -1; + } + + int bar(I i, InputStream stream) throws IOException { + return i.doIt(stream); + } +} diff --git a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java index 8faa3f15c23..7df7be35870 100644 --- a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java +++ b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.jps.build; +import com.google.common.collect.Lists; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.StreamUtil; @@ -23,6 +24,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; +import kotlin.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.cli.common.KotlinVersion; import org.jetbrains.jet.cli.common.arguments.CommonCompilerArguments; @@ -222,11 +224,18 @@ public class KotlinBuilder extends ModuleLevelBuilder { IncrementalCacheImpl cache = new IncrementalCacheImpl(KotlinBuilderModuleScriptGenerator.getIncrementalCacheDir(context)); try { + List> moduleIdsAndFiles = new ArrayList>(); + Map outDirectories = new HashMap(); + for (ModuleBuildTarget target : chunk.getTargets()) { + String targetId = target.getId(); + outDirectories.put(targetId, target.getOutputDir()); + for (String file : dirtyFilesHolder.getRemovedFiles(target)) { - cache.clearCacheForRemovedFile(target.getId(), new File(file)); + moduleIdsAndFiles.add(new Pair(targetId, new File(file))); } } + cache.clearCacheForRemovedFiles(moduleIdsAndFiles, outDirectories); boolean significantChanges = false; diff --git a/jps-plugin/src/org/jetbrains/jet/jps/incremental/IncrementalCacheImpl.kt b/jps-plugin/src/org/jetbrains/jet/jps/incremental/IncrementalCacheImpl.kt index e06193a161d..56a64060821 100644 --- a/jps-plugin/src/org/jetbrains/jet/jps/incremental/IncrementalCacheImpl.kt +++ b/jps-plugin/src/org/jetbrains/jet/jps/incremental/IncrementalCacheImpl.kt @@ -17,7 +17,6 @@ package org.jetbrains.jet.jps.incremental import java.io.File -import com.intellij.util.io.PersistentMap import com.intellij.util.io.PersistentHashMap import java.io.DataOutput import com.intellij.util.io.IOUtil @@ -36,6 +35,10 @@ import org.jetbrains.jet.lang.resolve.java.JvmClassName import java.util.HashSet import org.jetbrains.jet.lang.resolve.kotlin.incremental.IncrementalCache import java.util.HashMap +import com.google.common.collect.Maps +import org.jetbrains.jet.lang.resolve.java.PackageClassUtils +import com.intellij.util.containers.MultiMap +import com.intellij.openapi.util.io.FileUtil public class IncrementalCacheImpl(val baseDir: File): IncrementalCache { class object { @@ -54,16 +57,15 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache { if (classNameAndHeader == null) return false val (className, header) = classNameAndHeader - val classFqName = className.getFqNameForClassNameWithoutDollars() val annotationDataEncoded = header.annotationData if (annotationDataEncoded != null) { val data = BitEncoding.decodeBytes(annotationDataEncoded) when (header.kind) { KotlinClassHeader.Kind.PACKAGE_FACADE -> { - return protoMap.put(moduleId, classFqName.parent(), data) + return protoMap.put(moduleId, className, data) } KotlinClassHeader.Kind.CLASS -> { - return protoMap.put(moduleId, classFqName, data) + return protoMap.put(moduleId, className, data) } else -> { throw IllegalStateException("Unexpected kind with annotationData: ${header.kind}") @@ -73,14 +75,19 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache { if (header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART) { assert(sourceFiles.size == 1) { "Package part from several source files: $sourceFiles" } packagePartMap.putPackagePartSourceData(moduleId, sourceFiles.first(), className) - return constantsMap.process(className, fileBytes) + return constantsMap.process(moduleId, sourceFiles.first(), fileBytes) } return false } - public fun clearCacheForRemovedFile(moduleId: String, sourceFile: File) { - packagePartMap.remove(moduleId, sourceFile) + public fun clearCacheForRemovedFiles(moduleIdsAndFiles: Collection>, outDirectories: Map) { + for ((moduleId, sourceFile) in moduleIdsAndFiles) { + constantsMap.remove(moduleId, sourceFile) + packagePartMap.remove(moduleId, sourceFile) + } + + protoMap.clearOutdated(outDirectories) } public override fun getRemovedPackageParts(moduleId: String, compiledSourceFilesToFqName: Map): Collection { @@ -88,7 +95,7 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache { } public override fun getPackageData(moduleId: String, fqName: String): ByteArray? { - return protoMap[moduleId, fqName] + return protoMap[moduleId, JvmClassName.byFqNameWithoutInnerClasses(PackageClassUtils.getPackageClassFqName(FqName(fqName)))] } public fun close() { @@ -98,18 +105,23 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache { } private inner class ProtoMap { - private val map: PersistentMap = PersistentHashMap( + private val map: PersistentHashMap = PersistentHashMap( File(baseDir, PROTO_MAP), EnumeratorStringDescriptor(), ByteArrayExternalizer ) - private fun getKeyString(moduleId: String, fqName: FqName): String { - return moduleId + ":" + fqName + private fun getKeyString(moduleId: String, className: JvmClassName): String { + return moduleId + ":" + className.getInternalName() } - public fun put(moduleId: String, fqName: FqName, data: ByteArray): Boolean { - val key = getKeyString(moduleId, fqName) + private fun parseKeyString(key: String): Pair { + val colon = key.lastIndexOf(":") + return Pair(key.substring(0, colon), JvmClassName.byInternalName(key.substring(colon + 1))) + } + + public fun put(moduleId: String, className: JvmClassName, data: ByteArray): Boolean { + val key = getKeyString(moduleId, className) val oldData = map[key] if (Arrays.equals(data, oldData)) { return false @@ -118,8 +130,29 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache { return true } - public fun get(moduleId: String, fqName: String): ByteArray? { - return map[getKeyString(moduleId, FqName(fqName))] + public fun get(moduleId: String, className: JvmClassName): ByteArray? { + return map[getKeyString(moduleId, className)] + } + + public fun clearOutdated(outDirectories: Map) { + val keysToRemove = HashSet() + + map.processKeys { key -> + val (moduleId, className) = parseKeyString(key!!) + val outDir = outDirectories[moduleId] + if (outDir != null) { + val classFile = File(outDir, FileUtil.toSystemDependentName(className.getInternalName()) + ".class") + if (!classFile.exists()) { + keysToRemove.add(key) + } + } + + true + } + + for (key in keysToRemove) { + map.remove(key) + } } public fun close() { @@ -134,6 +167,10 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache { ConstantsMapExternalizer ) + private fun getKey(moduleId: String, sourceFile: File): String { + return moduleId + File.pathSeparator + sourceFile.getAbsolutePath() + } + private fun getConstantsMap(bytes: ByteArray): Map { val result = HashMap() @@ -149,12 +186,12 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache { return result } - public fun process(packagePartClass: JvmClassName, bytes: ByteArray): Boolean { - return put(packagePartClass, getConstantsMap(bytes)) + public fun process(moduleId: String, file: File, bytes: ByteArray): Boolean { + return put(moduleId, file, getConstantsMap(bytes)) } - private fun put(packagePartClass: JvmClassName, constantsMap: Map): Boolean { - val key = packagePartClass.getInternalName() + private fun put(moduleId: String, file: File, constantsMap: Map): Boolean { + val key = getKey(moduleId, file) val oldMap = map[key] if (oldMap == constantsMap) { @@ -164,6 +201,10 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache { return true } + public fun remove(moduleId: String, file: File) { + map.remove(getKey(moduleId, file)) + } + public fun close() { map.close() } @@ -203,7 +244,7 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache { override fun read(`in`: DataInput): Map? { val size = `in`.readInt() - val map = HashMap(size) + val map = Maps.newHashMapWithExpectedSize(size)!! for (i in size.indices) { val name = IOUtil.readString(`in`)!! @@ -273,6 +314,24 @@ public class IncrementalCacheImpl(val baseDir: File): IncrementalCache { return result } + public fun getModulesToPackages(): MultiMap { + val result = MultiMap.createSet() + + map.processKeysWithExistingMapping { key -> + val indexOf = key!!.indexOf(File.pathSeparator) + val moduleId = key.substring(0, indexOf) + val packagePartClassName = map[key]!! + + val packageFqName = JvmClassName.byInternalName(packagePartClassName).getFqNameForClassNameWithoutDollars().parent() + + result.putValue(moduleId, packageFqName) + + true + } + + return result + } + public fun close() { map.close() } diff --git a/jps-plugin/test/org/jetbrains/jet/jps/build/AbstractIncrementalJpsTest.kt b/jps-plugin/test/org/jetbrains/jet/jps/build/AbstractIncrementalJpsTest.kt index 1879580f7d1..3fb918b3e7e 100644 --- a/jps-plugin/test/org/jetbrains/jet/jps/build/AbstractIncrementalJpsTest.kt +++ b/jps-plugin/test/org/jetbrains/jet/jps/build/AbstractIncrementalJpsTest.kt @@ -88,10 +88,10 @@ public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() { val haveFilesWithNumbers = testDataDir.listFiles { it.getName().matches(".+\\.(new|delete)\\.\\d+$") }?.isNotEmpty() ?: false if (haveFilesWithoutNumbers && haveFilesWithNumbers) { - fail("Bad test data format: no files ending with \".new\" or \".delete\" found") + fail("Bad test data format: files ending with both unnumbered and numbered \".new\"/\".delete\" were found") } if (!haveFilesWithoutNumbers && !haveFilesWithNumbers) { - fail("Bad test data format: files ending with both unnumbered and numbered \".new\"/\".delete\" were found") + fail("Bad test data format: no files ending with \".new\" or \".delete\" found") } if (haveFilesWithoutNumbers) { @@ -111,7 +111,7 @@ public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() { rebuild() - assertEqualDirectories(outDir, outAfterMake, { it.name == "script.xml" }) + assertEqualDirectories(outDir, outAfterMake) FileUtil.delete(outAfterMake) } @@ -187,7 +187,16 @@ public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() { private class ModifyContent(name: String, val dataFile: File) : Modification(name) { override fun perform(workDir: File) { - dataFile.copyTo(File(workDir, "src/$name")) + val file = File(workDir, "src/$name") + + val oldLastModified = file.lastModified() + dataFile.copyTo(file) + + val newLastModified = file.lastModified() + if (newLastModified <= oldLastModified) { + //Mac OS and some versions of Linux truncate timestamp to nearest second + file.setLastModified(oldLastModified + 1000) + } } } diff --git a/jps-plugin/test/org/jetbrains/jet/jps/build/IncrementalJpsTestGenerated.java b/jps-plugin/test/org/jetbrains/jet/jps/build/IncrementalJpsTestGenerated.java index c8359bf9773..487dbaee338 100644 --- a/jps-plugin/test/org/jetbrains/jet/jps/build/IncrementalJpsTestGenerated.java +++ b/jps-plugin/test/org/jetbrains/jet/jps/build/IncrementalJpsTestGenerated.java @@ -32,10 +32,20 @@ import org.jetbrains.jet.jps.build.AbstractIncrementalJpsTest; @SuppressWarnings("all") @TestMetadata("jps-plugin/testData/incremental") public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest { + @TestMetadata("allConstants") + public void testAllConstants() throws Exception { + doTest("jps-plugin/testData/incremental/allConstants/"); + } + public void testAllFilesPresentInIncremental() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("jps-plugin/testData/incremental"), Pattern.compile("^([^\\.]+)$"), false); } + @TestMetadata("classRecreated") + public void testClassRecreated() throws Exception { + doTest("jps-plugin/testData/incremental/classRecreated/"); + } + @TestMetadata("classSignatureChanged") public void testClassSignatureChanged() throws Exception { doTest("jps-plugin/testData/incremental/classSignatureChanged/"); @@ -56,11 +66,31 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest { doTest("jps-plugin/testData/incremental/constantValue/"); } + @TestMetadata("dependencyClassReferenced") + public void testDependencyClassReferenced() throws Exception { + doTest("jps-plugin/testData/incremental/dependencyClassReferenced/"); + } + + @TestMetadata("filesExchangePackages") + public void testFilesExchangePackages() throws Exception { + doTest("jps-plugin/testData/incremental/filesExchangePackages/"); + } + @TestMetadata("independentClasses") public void testIndependentClasses() throws Exception { doTest("jps-plugin/testData/incremental/independentClasses/"); } + @TestMetadata("multiplePackagesModified") + public void testMultiplePackagesModified() throws Exception { + doTest("jps-plugin/testData/incremental/multiplePackagesModified/"); + } + + @TestMetadata("ourClassReferenced") + public void testOurClassReferenced() throws Exception { + doTest("jps-plugin/testData/incremental/ourClassReferenced/"); + } + @TestMetadata("packageFileAdded") public void testPackageFileAdded() throws Exception { doTest("jps-plugin/testData/incremental/packageFileAdded/"); @@ -86,6 +116,21 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest { doTest("jps-plugin/testData/incremental/packageFilesChangedInTurn/"); } + @TestMetadata("packageRecreated") + public void testPackageRecreated() throws Exception { + doTest("jps-plugin/testData/incremental/packageRecreated/"); + } + + @TestMetadata("packageRecreatedAfterRenaming") + public void testPackageRecreatedAfterRenaming() throws Exception { + doTest("jps-plugin/testData/incremental/packageRecreatedAfterRenaming/"); + } + + @TestMetadata("packageRemoved") + public void testPackageRemoved() throws Exception { + doTest("jps-plugin/testData/incremental/packageRemoved/"); + } + @TestMetadata("returnTypeChanged") public void testReturnTypeChanged() throws Exception { doTest("jps-plugin/testData/incremental/returnTypeChanged/"); @@ -96,6 +141,11 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest { doTest("jps-plugin/testData/incremental/simpleClassDependency/"); } + @TestMetadata("soleFileChangesPackage") + public void testSoleFileChangesPackage() throws Exception { + doTest("jps-plugin/testData/incremental/soleFileChangesPackage/"); + } + @TestMetadata("topLevelFunctionSameSignature") public void testTopLevelFunctionSameSignature() throws Exception { doTest("jps-plugin/testData/incremental/topLevelFunctionSameSignature/"); diff --git a/jps-plugin/test/org/jetbrains/jet/jps/build/classFilesComparison.kt b/jps-plugin/test/org/jetbrains/jet/jps/build/classFilesComparison.kt index d5cf4a3667e..1811f5ed2d4 100644 --- a/jps-plugin/test/org/jetbrains/jet/jps/build/classFilesComparison.kt +++ b/jps-plugin/test/org/jetbrains/jet/jps/build/classFilesComparison.kt @@ -39,7 +39,7 @@ import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass fun File.hash() = Files.hash(this, Hashing.crc32()) -fun getDirectoryString(dir: File, interestingPaths: List, ignore: (File) -> Boolean): String { +fun getDirectoryString(dir: File, interestingPaths: List): String { val buf = StringBuilder() val p = Printer(buf) @@ -52,10 +52,6 @@ fun getDirectoryString(dir: File, interestingPaths: List, ignore: (File) val children = listFiles!!.toList().sortBy { it.getName() }.sortBy { it.isDirectory() } for (child in children) { - if (ignore(child)) { - continue - } - if (child.isDirectory()) { p.println(child.name) addDirContent(child) @@ -82,10 +78,10 @@ fun getDirectoryString(dir: File, interestingPaths: List, ignore: (File) return buf.toString() } -fun getAllRelativePaths(dir: File, ignore: (File) -> Boolean): Set { +fun getAllRelativePaths(dir: File): Set { val result = HashSet() FileUtil.processFilesRecursively(dir) { - if (it!!.isFile() && !ignore(it)) { + if (it!!.isFile()) { result.add(FileUtil.getRelativePath(dir, it)!!) } @@ -95,16 +91,16 @@ fun getAllRelativePaths(dir: File, ignore: (File) -> Boolean): Set { return result } -fun assertEqualDirectories(expected: File, actual: File, ignore: (File) -> Boolean) { - val pathsInExpected = getAllRelativePaths(expected, ignore) - val pathsInActual = getAllRelativePaths(actual, ignore) +fun assertEqualDirectories(expected: File, actual: File) { + val pathsInExpected = getAllRelativePaths(expected) + val pathsInActual = getAllRelativePaths(actual) val changedPaths = Sets.intersection(pathsInExpected, pathsInActual) .filter { !Arrays.equals(File(expected, it).readBytes(), File(actual, it).readBytes()) } .sort() - val expectedString = getDirectoryString(expected, changedPaths, ignore) - val actualString = getDirectoryString(actual, changedPaths, ignore) + val expectedString = getDirectoryString(expected, changedPaths) + val actualString = getDirectoryString(actual, changedPaths) assertEquals(expectedString, actualString) } diff --git a/jps-plugin/testData/incremental/allConstants/build.log b/jps-plugin/testData/incremental/allConstants/build.log new file mode 100644 index 00000000000..22f4d62f635 --- /dev/null +++ b/jps-plugin/testData/incremental/allConstants/build.log @@ -0,0 +1,22 @@ +Cleaning output files: +out/production/module/test/TestPackage-const-*.class +out/production/module/test/TestPackage.class +End of files +Compiling files: +src/const.kt +End of files + + +Cleaning output files: +out/production/module/test/TestPackage-const-*.class +out/production/module/test/TestPackage.class +End of files +Compiling files: +src/const.kt +End of files +Cleaning output files: +out/production/module/test/Usage.class +End of files +Compiling files: +src/usage.kt +End of files diff --git a/jps-plugin/testData/incremental/allConstants/const.kt b/jps-plugin/testData/incremental/allConstants/const.kt new file mode 100644 index 00000000000..d0d300c1312 --- /dev/null +++ b/jps-plugin/testData/incremental/allConstants/const.kt @@ -0,0 +1,12 @@ +package test + +val b: Byte = 100 +val s: Short = 20000 +val i: Int = 2000000 +val l: Long = 2000000000000L +val f: Float = 3.14f +val d: Double = 3.14 +val bb: Boolean = true +val c: Char = '\u03c0' // pi symbol + +val str: String = ":)" diff --git a/jps-plugin/testData/incremental/allConstants/const.kt.new.1 b/jps-plugin/testData/incremental/allConstants/const.kt.new.1 new file mode 100644 index 00000000000..26796869ddc --- /dev/null +++ b/jps-plugin/testData/incremental/allConstants/const.kt.new.1 @@ -0,0 +1,12 @@ +package test + +val b: Byte = 50 + 50 +val s: Short = 10000 + 10000 +val i: Int = 1000000 + 1000000 +val l: Long = 1000000000000L + 1000000000000L +val f: Float = 0.0f + 3.14f +val d: Double = 0.0 + 3.14 +val bb: Boolean = !false +val c: Char = '\u03c0' // pi symbol + +val str: String = ":)" diff --git a/jps-plugin/testData/incremental/allConstants/const.kt.new.2 b/jps-plugin/testData/incremental/allConstants/const.kt.new.2 new file mode 100644 index 00000000000..668b4009dce --- /dev/null +++ b/jps-plugin/testData/incremental/allConstants/const.kt.new.2 @@ -0,0 +1,12 @@ +package test + +val b: Byte = 0 +val s: Short = 0 +val i: Int = 0 +val l: Long = 0 +val f: Float = 0.0f +val d: Double = 0.0 +val bb: Boolean = false +val c: Char = 'x' + +val str: String = ":(" diff --git a/jps-plugin/testData/incremental/allConstants/usage.kt b/jps-plugin/testData/incremental/allConstants/usage.kt new file mode 100644 index 00000000000..a52256d1a83 --- /dev/null +++ b/jps-plugin/testData/incremental/allConstants/usage.kt @@ -0,0 +1,4 @@ +package test + +deprecated("$b $s $i $l $f $d $bb $c $str") +class Usage diff --git a/jps-plugin/testData/incremental/classRecreated/A.kt.new.2 b/jps-plugin/testData/incremental/classRecreated/A.kt.new.2 new file mode 100644 index 00000000000..1b0178fd9be --- /dev/null +++ b/jps-plugin/testData/incremental/classRecreated/A.kt.new.2 @@ -0,0 +1,3 @@ +package test + +class A diff --git a/jps-plugin/testData/incremental/classRecreated/a.kt b/jps-plugin/testData/incremental/classRecreated/a.kt new file mode 100644 index 00000000000..1b0178fd9be --- /dev/null +++ b/jps-plugin/testData/incremental/classRecreated/a.kt @@ -0,0 +1,3 @@ +package test + +class A diff --git a/jps-plugin/testData/incremental/classRecreated/a.kt.delete.1 b/jps-plugin/testData/incremental/classRecreated/a.kt.delete.1 new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/jps-plugin/testData/incremental/classRecreated/a.kt.delete.1 @@ -0,0 +1 @@ + diff --git a/jps-plugin/testData/incremental/classRecreated/build.log b/jps-plugin/testData/incremental/classRecreated/build.log new file mode 100644 index 00000000000..d59630c7ce7 --- /dev/null +++ b/jps-plugin/testData/incremental/classRecreated/build.log @@ -0,0 +1,17 @@ +Cleaning output files: +out/production/module/test/A.class +End of files +Compiling files: +End of files + + +Compiling files: +src/A.kt +End of files +Cleaning output files: +out/production/module/test/TestPackage-other-*.class +out/production/module/test/TestPackage.class +End of files +Compiling files: +src/other.kt +End of files \ No newline at end of file diff --git a/jps-plugin/testData/incremental/classRecreated/other.kt b/jps-plugin/testData/incremental/classRecreated/other.kt new file mode 100644 index 00000000000..dc156549ce5 --- /dev/null +++ b/jps-plugin/testData/incremental/classRecreated/other.kt @@ -0,0 +1,4 @@ +package test + +fun other() { +} diff --git a/jps-plugin/testData/incremental/dependencyClassReferenced/a.kt b/jps-plugin/testData/incremental/dependencyClassReferenced/a.kt new file mode 100644 index 00000000000..89692d95832 --- /dev/null +++ b/jps-plugin/testData/incremental/dependencyClassReferenced/a.kt @@ -0,0 +1,6 @@ +package test + +fun a(ref: kotlin.test.Asserter) { + b(ref) + println(":)") +} \ No newline at end of file diff --git a/jps-plugin/testData/incremental/dependencyClassReferenced/a.kt.new b/jps-plugin/testData/incremental/dependencyClassReferenced/a.kt.new new file mode 100644 index 00000000000..89692d95832 --- /dev/null +++ b/jps-plugin/testData/incremental/dependencyClassReferenced/a.kt.new @@ -0,0 +1,6 @@ +package test + +fun a(ref: kotlin.test.Asserter) { + b(ref) + println(":)") +} \ No newline at end of file diff --git a/jps-plugin/testData/incremental/dependencyClassReferenced/b.kt b/jps-plugin/testData/incremental/dependencyClassReferenced/b.kt new file mode 100644 index 00000000000..9addb367f04 --- /dev/null +++ b/jps-plugin/testData/incremental/dependencyClassReferenced/b.kt @@ -0,0 +1,6 @@ +package test + +fun b(ref: kotlin.test.Asserter) { + a(ref) + println(":)") +} \ No newline at end of file diff --git a/jps-plugin/testData/incremental/dependencyClassReferenced/build.log b/jps-plugin/testData/incremental/dependencyClassReferenced/build.log new file mode 100644 index 00000000000..37112dda098 --- /dev/null +++ b/jps-plugin/testData/incremental/dependencyClassReferenced/build.log @@ -0,0 +1,7 @@ +Cleaning output files: +out/production/module/test/TestPackage-a-*.class +out/production/module/test/TestPackage.class +End of files +Compiling files: +src/a.kt +End of files diff --git a/jps-plugin/testData/incremental/filesExchangePackages/a.kt b/jps-plugin/testData/incremental/filesExchangePackages/a.kt new file mode 100644 index 00000000000..058137655b8 --- /dev/null +++ b/jps-plugin/testData/incremental/filesExchangePackages/a.kt @@ -0,0 +1,3 @@ +package foo + +fun a() = "a" diff --git a/jps-plugin/testData/incremental/filesExchangePackages/b.kt b/jps-plugin/testData/incremental/filesExchangePackages/b.kt new file mode 100644 index 00000000000..d838bdff1a4 --- /dev/null +++ b/jps-plugin/testData/incremental/filesExchangePackages/b.kt @@ -0,0 +1,3 @@ +package foo + +fun b() = "b" diff --git a/jps-plugin/testData/incremental/filesExchangePackages/b.kt.new b/jps-plugin/testData/incremental/filesExchangePackages/b.kt.new new file mode 100644 index 00000000000..75675fcebb4 --- /dev/null +++ b/jps-plugin/testData/incremental/filesExchangePackages/b.kt.new @@ -0,0 +1,3 @@ +package bar + +fun b() = "b" diff --git a/jps-plugin/testData/incremental/filesExchangePackages/build.log b/jps-plugin/testData/incremental/filesExchangePackages/build.log new file mode 100644 index 00000000000..492218cc4a6 --- /dev/null +++ b/jps-plugin/testData/incremental/filesExchangePackages/build.log @@ -0,0 +1,17 @@ +Cleaning output files: +out/production/module/bar/BarPackage-c-*.class +out/production/module/bar/BarPackage.class +out/production/module/foo/FooPackage-b-*.class +out/production/module/foo/FooPackage.class +End of files +Compiling files: +src/b.kt +src/c.kt +End of files +Cleaning output files: +out/production/module/foo/FooPackage-a-*.class +out/production/module/foo/FooPackage.class +End of files +Compiling files: +src/a.kt +End of files diff --git a/jps-plugin/testData/incremental/filesExchangePackages/c.kt b/jps-plugin/testData/incremental/filesExchangePackages/c.kt new file mode 100644 index 00000000000..ba081bb0bbd --- /dev/null +++ b/jps-plugin/testData/incremental/filesExchangePackages/c.kt @@ -0,0 +1,3 @@ +package bar + +fun c() = "c" diff --git a/jps-plugin/testData/incremental/filesExchangePackages/c.kt.new b/jps-plugin/testData/incremental/filesExchangePackages/c.kt.new new file mode 100644 index 00000000000..e51d910bb9d --- /dev/null +++ b/jps-plugin/testData/incremental/filesExchangePackages/c.kt.new @@ -0,0 +1,3 @@ +package foo + +fun c() = "c" diff --git a/jps-plugin/testData/incremental/multiplePackagesModified/a1.kt b/jps-plugin/testData/incremental/multiplePackagesModified/a1.kt new file mode 100644 index 00000000000..2bd705934bc --- /dev/null +++ b/jps-plugin/testData/incremental/multiplePackagesModified/a1.kt @@ -0,0 +1,3 @@ +package a + +fun a1() = ":)" \ No newline at end of file diff --git a/jps-plugin/testData/incremental/multiplePackagesModified/a2.kt.new b/jps-plugin/testData/incremental/multiplePackagesModified/a2.kt.new new file mode 100644 index 00000000000..4e46bd9087f --- /dev/null +++ b/jps-plugin/testData/incremental/multiplePackagesModified/a2.kt.new @@ -0,0 +1,3 @@ +package a + +fun a2() = ":))" \ No newline at end of file diff --git a/jps-plugin/testData/incremental/multiplePackagesModified/b1.kt b/jps-plugin/testData/incremental/multiplePackagesModified/b1.kt new file mode 100644 index 00000000000..21999b4bfe6 --- /dev/null +++ b/jps-plugin/testData/incremental/multiplePackagesModified/b1.kt @@ -0,0 +1,3 @@ +package b + +fun b1() = ":(" \ No newline at end of file diff --git a/jps-plugin/testData/incremental/multiplePackagesModified/b2.kt b/jps-plugin/testData/incremental/multiplePackagesModified/b2.kt new file mode 100644 index 00000000000..d2f49a90033 --- /dev/null +++ b/jps-plugin/testData/incremental/multiplePackagesModified/b2.kt @@ -0,0 +1,3 @@ +package b + +fun b2() = ":((" \ No newline at end of file diff --git a/jps-plugin/testData/incremental/multiplePackagesModified/b2.kt.delete b/jps-plugin/testData/incremental/multiplePackagesModified/b2.kt.delete new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jps-plugin/testData/incremental/multiplePackagesModified/build.log b/jps-plugin/testData/incremental/multiplePackagesModified/build.log new file mode 100644 index 00000000000..914a8b69528 --- /dev/null +++ b/jps-plugin/testData/incremental/multiplePackagesModified/build.log @@ -0,0 +1,17 @@ +Cleaning output files: +out/production/module/b/BPackage-b2-*.class +out/production/module/b/BPackage.class +End of files +Compiling files: +src/a2.kt +End of files +Cleaning output files: +out/production/module/a/APackage-a1-*.class +out/production/module/a/APackage.class +out/production/module/b/BPackage-b1-*.class +out/production/module/b/BPackage.class +End of files +Compiling files: +src/a1.kt +src/b1.kt +End of files diff --git a/jps-plugin/testData/incremental/ourClassReferenced/Klass.kt b/jps-plugin/testData/incremental/ourClassReferenced/Klass.kt new file mode 100644 index 00000000000..a8ac38430eb --- /dev/null +++ b/jps-plugin/testData/incremental/ourClassReferenced/Klass.kt @@ -0,0 +1,3 @@ +package klass + +class Klass \ No newline at end of file diff --git a/jps-plugin/testData/incremental/ourClassReferenced/Klass.kt.new.2 b/jps-plugin/testData/incremental/ourClassReferenced/Klass.kt.new.2 new file mode 100644 index 00000000000..a8ac38430eb --- /dev/null +++ b/jps-plugin/testData/incremental/ourClassReferenced/Klass.kt.new.2 @@ -0,0 +1,3 @@ +package klass + +class Klass \ No newline at end of file diff --git a/jps-plugin/testData/incremental/ourClassReferenced/a.kt b/jps-plugin/testData/incremental/ourClassReferenced/a.kt new file mode 100644 index 00000000000..3682a9d2913 --- /dev/null +++ b/jps-plugin/testData/incremental/ourClassReferenced/a.kt @@ -0,0 +1,8 @@ +package test + +import klass.* + +fun a(klass: Klass) { + b(klass) + println(":)") +} \ No newline at end of file diff --git a/jps-plugin/testData/incremental/ourClassReferenced/a.kt.new.1 b/jps-plugin/testData/incremental/ourClassReferenced/a.kt.new.1 new file mode 100644 index 00000000000..3682a9d2913 --- /dev/null +++ b/jps-plugin/testData/incremental/ourClassReferenced/a.kt.new.1 @@ -0,0 +1,8 @@ +package test + +import klass.* + +fun a(klass: Klass) { + b(klass) + println(":)") +} \ No newline at end of file diff --git a/jps-plugin/testData/incremental/ourClassReferenced/a.kt.new.2 b/jps-plugin/testData/incremental/ourClassReferenced/a.kt.new.2 new file mode 100644 index 00000000000..3682a9d2913 --- /dev/null +++ b/jps-plugin/testData/incremental/ourClassReferenced/a.kt.new.2 @@ -0,0 +1,8 @@ +package test + +import klass.* + +fun a(klass: Klass) { + b(klass) + println(":)") +} \ No newline at end of file diff --git a/jps-plugin/testData/incremental/ourClassReferenced/b.kt b/jps-plugin/testData/incremental/ourClassReferenced/b.kt new file mode 100644 index 00000000000..0d41f8e3417 --- /dev/null +++ b/jps-plugin/testData/incremental/ourClassReferenced/b.kt @@ -0,0 +1,8 @@ +package test + +import klass.* + +fun b(klass: Klass) { + a(klass) + println(":)") +} \ No newline at end of file diff --git a/jps-plugin/testData/incremental/ourClassReferenced/build.log b/jps-plugin/testData/incremental/ourClassReferenced/build.log new file mode 100644 index 00000000000..ccf56d9e65b --- /dev/null +++ b/jps-plugin/testData/incremental/ourClassReferenced/build.log @@ -0,0 +1,18 @@ +Cleaning output files: +out/production/module/test/TestPackage-a-*.class +out/production/module/test/TestPackage.class +End of files +Compiling files: +src/a.kt +End of files + + +Cleaning output files: +out/production/module/klass/Klass.class +out/production/module/test/TestPackage-a-*.class +out/production/module/test/TestPackage.class +End of files +Compiling files: +src/Klass.kt +src/a.kt +End of files diff --git a/jps-plugin/testData/incremental/packageRecreated/a.kt b/jps-plugin/testData/incremental/packageRecreated/a.kt new file mode 100644 index 00000000000..30ca24b5576 --- /dev/null +++ b/jps-plugin/testData/incremental/packageRecreated/a.kt @@ -0,0 +1,3 @@ +package test + +fun a() = "a" diff --git a/jps-plugin/testData/incremental/packageRecreated/a.kt.delete.1 b/jps-plugin/testData/incremental/packageRecreated/a.kt.delete.1 new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/jps-plugin/testData/incremental/packageRecreated/a.kt.delete.1 @@ -0,0 +1 @@ + diff --git a/jps-plugin/testData/incremental/packageRecreated/b.kt.new.2 b/jps-plugin/testData/incremental/packageRecreated/b.kt.new.2 new file mode 100644 index 00000000000..5c782f47a25 --- /dev/null +++ b/jps-plugin/testData/incremental/packageRecreated/b.kt.new.2 @@ -0,0 +1,3 @@ +package test + +fun b() = "b" diff --git a/jps-plugin/testData/incremental/packageRecreated/build.log b/jps-plugin/testData/incremental/packageRecreated/build.log new file mode 100644 index 00000000000..73408189236 --- /dev/null +++ b/jps-plugin/testData/incremental/packageRecreated/build.log @@ -0,0 +1,11 @@ +Cleaning output files: +out/production/module/test/TestPackage-a-*.class +out/production/module/test/TestPackage.class +End of files +Compiling files: +End of files + + +Compiling files: +src/b.kt +End of files diff --git a/jps-plugin/testData/incremental/packageRecreatedAfterRenaming/a.kt b/jps-plugin/testData/incremental/packageRecreatedAfterRenaming/a.kt new file mode 100644 index 00000000000..30ca24b5576 --- /dev/null +++ b/jps-plugin/testData/incremental/packageRecreatedAfterRenaming/a.kt @@ -0,0 +1,3 @@ +package test + +fun a() = "a" diff --git a/jps-plugin/testData/incremental/packageRecreatedAfterRenaming/a.kt.new.1 b/jps-plugin/testData/incremental/packageRecreatedAfterRenaming/a.kt.new.1 new file mode 100644 index 00000000000..9d39f81713e --- /dev/null +++ b/jps-plugin/testData/incremental/packageRecreatedAfterRenaming/a.kt.new.1 @@ -0,0 +1,3 @@ +package test2 + +fun a() = "a" diff --git a/jps-plugin/testData/incremental/packageRecreatedAfterRenaming/b.kt.new.2 b/jps-plugin/testData/incremental/packageRecreatedAfterRenaming/b.kt.new.2 new file mode 100644 index 00000000000..5c782f47a25 --- /dev/null +++ b/jps-plugin/testData/incremental/packageRecreatedAfterRenaming/b.kt.new.2 @@ -0,0 +1,3 @@ +package test + +fun b() = "b" diff --git a/jps-plugin/testData/incremental/packageRecreatedAfterRenaming/build.log b/jps-plugin/testData/incremental/packageRecreatedAfterRenaming/build.log new file mode 100644 index 00000000000..7cb5ae7d3e1 --- /dev/null +++ b/jps-plugin/testData/incremental/packageRecreatedAfterRenaming/build.log @@ -0,0 +1,19 @@ +Cleaning output files: +out/production/module/test/TestPackage-a-*.class +out/production/module/test/TestPackage.class +End of files +Compiling files: +src/a.kt +End of files + + +Compiling files: +src/b.kt +End of files +Cleaning output files: +out/production/module/test2/Test2Package-a-*.class +out/production/module/test2/Test2Package.class +End of files +Compiling files: +src/a.kt +End of files diff --git a/jps-plugin/testData/incremental/packageRemoved/a.kt b/jps-plugin/testData/incremental/packageRemoved/a.kt new file mode 100644 index 00000000000..30ca24b5576 --- /dev/null +++ b/jps-plugin/testData/incremental/packageRemoved/a.kt @@ -0,0 +1,3 @@ +package test + +fun a() = "a" diff --git a/jps-plugin/testData/incremental/packageRemoved/a.kt.delete b/jps-plugin/testData/incremental/packageRemoved/a.kt.delete new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jps-plugin/testData/incremental/packageRemoved/b.kt b/jps-plugin/testData/incremental/packageRemoved/b.kt new file mode 100644 index 00000000000..5c782f47a25 --- /dev/null +++ b/jps-plugin/testData/incremental/packageRemoved/b.kt @@ -0,0 +1,3 @@ +package test + +fun b() = "b" diff --git a/jps-plugin/testData/incremental/packageRemoved/b.kt.delete b/jps-plugin/testData/incremental/packageRemoved/b.kt.delete new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jps-plugin/testData/incremental/packageRemoved/build.log b/jps-plugin/testData/incremental/packageRemoved/build.log new file mode 100644 index 00000000000..c307a197264 --- /dev/null +++ b/jps-plugin/testData/incremental/packageRemoved/build.log @@ -0,0 +1,9 @@ +Cleaning output files: +out/production/module/test/TestPackage-a-*.class +out/production/module/test/TestPackage.class +End of files +Cleaning output files: +out/production/module/test/TestPackage-b-*.class +End of files +Compiling files: +End of files \ No newline at end of file diff --git a/jps-plugin/testData/incremental/soleFileChangesPackage/a.kt b/jps-plugin/testData/incremental/soleFileChangesPackage/a.kt new file mode 100644 index 00000000000..058137655b8 --- /dev/null +++ b/jps-plugin/testData/incremental/soleFileChangesPackage/a.kt @@ -0,0 +1,3 @@ +package foo + +fun a() = "a" diff --git a/jps-plugin/testData/incremental/soleFileChangesPackage/a.kt.new b/jps-plugin/testData/incremental/soleFileChangesPackage/a.kt.new new file mode 100644 index 00000000000..eb3b7b757d2 --- /dev/null +++ b/jps-plugin/testData/incremental/soleFileChangesPackage/a.kt.new @@ -0,0 +1,4 @@ +package bar + +fun a() = "a" +fun aa() = "aa" diff --git a/jps-plugin/testData/incremental/soleFileChangesPackage/build.log b/jps-plugin/testData/incremental/soleFileChangesPackage/build.log new file mode 100644 index 00000000000..3c8fdd9ea17 --- /dev/null +++ b/jps-plugin/testData/incremental/soleFileChangesPackage/build.log @@ -0,0 +1,7 @@ +Cleaning output files: +out/production/module/foo/FooPackage-a-*.class +out/production/module/foo/FooPackage.class +End of files +Compiling files: +src/a.kt +End of files \ No newline at end of file diff --git a/js/js.libraries/src/core/javalang.kt b/js/js.libraries/src/core/javalang.kt index fa927038af5..df87315b7f0 100644 --- a/js/js.libraries/src/core/javalang.kt +++ b/js/js.libraries/src/core/javalang.kt @@ -40,7 +40,7 @@ public trait Comparable { library public trait Appendable { public open fun append(csq: CharSequence?): Appendable - //public open fun append(csq: CharSequence?, start: Int, end: Int): Appendable + public open fun append(csq: CharSequence?, start: Int, end: Int): Appendable public open fun append(c: Char): Appendable } @@ -48,8 +48,7 @@ library public class StringBuilder() : Appendable { override fun append(c: Char): StringBuilder = js.noImpl override fun append(csq: CharSequence?): StringBuilder = js.noImpl - //TODO - //override fun append(csq: CharSequence?, start: Int, end: Int): StringBuilder = js.noImpl + override fun append(csq: CharSequence?, start: Int, end: Int): StringBuilder = js.noImpl public fun append(obj: Any?): StringBuilder = js.noImpl public fun reverse(): StringBuilder = js.noImpl override fun toString(): String = js.noImpl diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibStringBuilderTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibStringBuilderTest.java new file mode 100644 index 00000000000..3c4bf9c0755 --- /dev/null +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibStringBuilderTest.java @@ -0,0 +1,10 @@ +package org.jetbrains.k2js.test.semantics; + +import junit.framework.Test; + +@SuppressWarnings("JUnitTestCaseWithNoTests") +public final class StdLibStringBuilderTest extends JsUnitTestBase { + public static Test suite() throws Exception { + return createTestSuiteForFile("libraries/stdlib/test/text/StringBuilderTest.kt"); + } +} diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibStringTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibStringTest.java new file mode 100644 index 00000000000..1a05014230a --- /dev/null +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibStringTest.java @@ -0,0 +1,10 @@ +package org.jetbrains.k2js.test.semantics; + +import junit.framework.Test; + +@SuppressWarnings("JUnitTestCaseWithNoTests") +public final class StdLibStringTest extends JsUnitTestBase { + public static Test suite() throws Exception { + return createTestSuiteForFile("libraries/stdlib/test/text/StringTest.kt"); + } +} diff --git a/js/js.translator/src/org/jetbrains/k2js/config/Config.java b/js/js.translator/src/org/jetbrains/k2js/config/Config.java index e570c104029..aea3607710f 100644 --- a/js/js.translator/src/org/jetbrains/k2js/config/Config.java +++ b/js/js.translator/src/org/jetbrains/k2js/config/Config.java @@ -139,6 +139,7 @@ public abstract class Config { "/kotlin/Ranges.kt", "/kotlin/Numbers.kt", "/kotlin/text/Strings.kt", + "/kotlin/text/StringBuilder.kt", "/kotlin/dom/Dom.kt", "/kotlin/test/Test.kt" ); diff --git a/js/js.translator/testData/kotlin_lib.js b/js/js.translator/testData/kotlin_lib.js index 39e358bd7df..acfac5fbfb2 100644 --- a/js/js.translator/testData/kotlin_lib.js +++ b/js/js.translator/testData/kotlin_lib.js @@ -546,6 +546,11 @@ }, isEmpty: function () { return this.start > this.end; + }, + equals_za3rmp$: function(other) { + if (other == null) + return false; + return this.start === other.start && this.end === other.end && this.increment === other.increment; } }); @@ -649,8 +654,15 @@ function () { this.string = ""; }, { - append: function (obj) { - this.string = this.string + obj.toString(); + append: function (obj, from, to) { + if (from == undefined && to == undefined) { + this.string = this.string + obj.toString(); + } else if (to == undefined) { + this.string = this.string + obj.toString().substring(from); + } else { + this.string = this.string + obj.toString().substring(from, to); + } + return this; }, reverse: function () { diff --git a/libraries/stdlib/src/generated/_Generators.kt b/libraries/stdlib/src/generated/_Generators.kt index 5bdebb21b70..4949aa2280c 100644 --- a/libraries/stdlib/src/generated/_Generators.kt +++ b/libraries/stdlib/src/generated/_Generators.kt @@ -7,6 +7,299 @@ package kotlin import java.util.* +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun Array.merge(array: Array, transform: (T, R) -> V): List { + val first = iterator() + val second = array.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun BooleanArray.merge(array: Array, transform: (Boolean, R) -> V): List { + val first = iterator() + val second = array.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun ByteArray.merge(array: Array, transform: (Byte, R) -> V): List { + val first = iterator() + val second = array.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun CharArray.merge(array: Array, transform: (Char, R) -> V): List { + val first = iterator() + val second = array.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun DoubleArray.merge(array: Array, transform: (Double, R) -> V): List { + val first = iterator() + val second = array.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun FloatArray.merge(array: Array, transform: (Float, R) -> V): List { + val first = iterator() + val second = array.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun IntArray.merge(array: Array, transform: (Int, R) -> V): List { + val first = iterator() + val second = array.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun LongArray.merge(array: Array, transform: (Long, R) -> V): List { + val first = iterator() + val second = array.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun ShortArray.merge(array: Array, transform: (Short, R) -> V): List { + val first = iterator() + val second = array.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun Iterable.merge(array: Array, transform: (T, R) -> V): List { + val first = iterator() + val second = array.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun String.merge(array: Array, transform: (Char, R) -> V): List { + val first = iterator() + val second = array.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun Array.merge(other: Iterable, transform: (T, R) -> V): List { + val first = iterator() + val second = other.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun BooleanArray.merge(other: Iterable, transform: (Boolean, R) -> V): List { + val first = iterator() + val second = other.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun ByteArray.merge(other: Iterable, transform: (Byte, R) -> V): List { + val first = iterator() + val second = other.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun CharArray.merge(other: Iterable, transform: (Char, R) -> V): List { + val first = iterator() + val second = other.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun DoubleArray.merge(other: Iterable, transform: (Double, R) -> V): List { + val first = iterator() + val second = other.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun FloatArray.merge(other: Iterable, transform: (Float, R) -> V): List { + val first = iterator() + val second = other.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun IntArray.merge(other: Iterable, transform: (Int, R) -> V): List { + val first = iterator() + val second = other.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun LongArray.merge(other: Iterable, transform: (Long, R) -> V): List { + val first = iterator() + val second = other.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun ShortArray.merge(other: Iterable, transform: (Short, R) -> V): List { + val first = iterator() + val second = other.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun Iterable.merge(other: Iterable, transform: (T, R) -> V): List { + val first = iterator() + val second = other.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + */ +public inline fun String.merge(other: Iterable, transform: (Char, R) -> V): List { + val first = iterator() + val second = other.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list +} + +/** + * Returns a stream of values built from elements of both collections with same indexes using provided *transform*. Stream has length of shortest stream. + */ +public fun Stream.merge(stream: Stream, transform: (T, R) -> V): Stream { + return MergingStream(this, stream, transform) +} + /** * Splits original collection into pair of collections, * where *first* collection contains elements for which predicate yielded *true*, @@ -518,286 +811,154 @@ public fun Stream.plus(stream: Stream): Stream { * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun Array.zip(array: Array): List> { - val first = iterator() - val second = array.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(array) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun BooleanArray.zip(array: Array): List> { - val first = iterator() - val second = array.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(array) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun ByteArray.zip(array: Array): List> { - val first = iterator() - val second = array.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(array) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun CharArray.zip(array: Array): List> { - val first = iterator() - val second = array.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(array) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun DoubleArray.zip(array: Array): List> { - val first = iterator() - val second = array.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(array) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun FloatArray.zip(array: Array): List> { - val first = iterator() - val second = array.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(array) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun IntArray.zip(array: Array): List> { - val first = iterator() - val second = array.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(array) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun LongArray.zip(array: Array): List> { - val first = iterator() - val second = array.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(array) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun ShortArray.zip(array: Array): List> { - val first = iterator() - val second = array.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(array) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun Iterable.zip(array: Array): List> { - val first = iterator() - val second = array.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(array) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun String.zip(array: Array): List> { - val first = iterator() - val second = array.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(array) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun Array.zip(other: Iterable): List> { - val first = iterator() - val second = other.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(other) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun BooleanArray.zip(other: Iterable): List> { - val first = iterator() - val second = other.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(other) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun ByteArray.zip(other: Iterable): List> { - val first = iterator() - val second = other.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(other) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun CharArray.zip(other: Iterable): List> { - val first = iterator() - val second = other.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(other) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun DoubleArray.zip(other: Iterable): List> { - val first = iterator() - val second = other.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(other) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun FloatArray.zip(other: Iterable): List> { - val first = iterator() - val second = other.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(other) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun IntArray.zip(other: Iterable): List> { - val first = iterator() - val second = other.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(other) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun LongArray.zip(other: Iterable): List> { - val first = iterator() - val second = other.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(other) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun ShortArray.zip(other: Iterable): List> { - val first = iterator() - val second = other.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(other) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun Iterable.zip(other: Iterable): List> { - val first = iterator() - val second = other.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(other) { (t1, t2) -> t1 to t2 } } /** * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. */ public fun String.zip(other: Iterable): List> { - val first = iterator() - val second = other.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(other) { (t1, t2) -> t1 to t2 } } /** @@ -814,9 +975,9 @@ public fun String.zip(other: String): List> { } /** - * Returns a stream of pairs built from elements of both collections with same indexes. List has length of shortest collection. + * Returns a stream of pairs built from elements of both collections with same indexes. Stream has length of shortest stream. */ public fun Stream.zip(stream: Stream): Stream> { - return ZippingStream(this, stream) + return MergingStream(this, stream) { (t1, t2) -> t1 to t2 } } diff --git a/libraries/stdlib/src/generated/_Sets.kt b/libraries/stdlib/src/generated/_Sets.kt new file mode 100644 index 00000000000..961e19e8a9a --- /dev/null +++ b/libraries/stdlib/src/generated/_Sets.kt @@ -0,0 +1,440 @@ +package kotlin + +// +// NOTE THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + +import java.util.* + +/** + * Returns a set containing all distinct elements from the given collection. + */ +public fun Array.distinct(): Set { + return this.toMutableSet() +} + +/** + * Returns a set containing all distinct elements from the given collection. + */ +public fun BooleanArray.distinct(): Set { + return this.toMutableSet() +} + +/** + * Returns a set containing all distinct elements from the given collection. + */ +public fun ByteArray.distinct(): Set { + return this.toMutableSet() +} + +/** + * Returns a set containing all distinct elements from the given collection. + */ +public fun CharArray.distinct(): Set { + return this.toMutableSet() +} + +/** + * Returns a set containing all distinct elements from the given collection. + */ +public fun DoubleArray.distinct(): Set { + return this.toMutableSet() +} + +/** + * Returns a set containing all distinct elements from the given collection. + */ +public fun FloatArray.distinct(): Set { + return this.toMutableSet() +} + +/** + * Returns a set containing all distinct elements from the given collection. + */ +public fun IntArray.distinct(): Set { + return this.toMutableSet() +} + +/** + * Returns a set containing all distinct elements from the given collection. + */ +public fun LongArray.distinct(): Set { + return this.toMutableSet() +} + +/** + * Returns a set containing all distinct elements from the given collection. + */ +public fun ShortArray.distinct(): Set { + return this.toMutableSet() +} + +/** + * Returns a set containing all distinct elements from the given collection. + */ +public fun Iterable.distinct(): Set { + return this.toMutableSet() +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun Array.intersect(other: Iterable): Set { + val set = this.toMutableSet() + set.retainAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun BooleanArray.intersect(other: Iterable): Set { + val set = this.toMutableSet() + set.retainAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun ByteArray.intersect(other: Iterable): Set { + val set = this.toMutableSet() + set.retainAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun CharArray.intersect(other: Iterable): Set { + val set = this.toMutableSet() + set.retainAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun DoubleArray.intersect(other: Iterable): Set { + val set = this.toMutableSet() + set.retainAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun FloatArray.intersect(other: Iterable): Set { + val set = this.toMutableSet() + set.retainAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun IntArray.intersect(other: Iterable): Set { + val set = this.toMutableSet() + set.retainAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun LongArray.intersect(other: Iterable): Set { + val set = this.toMutableSet() + set.retainAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun ShortArray.intersect(other: Iterable): Set { + val set = this.toMutableSet() + set.retainAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun Iterable.intersect(other: Iterable): Set { + val set = this.toMutableSet() + set.retainAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun Array.subtract(other: Iterable): Set { + val set = this.toMutableSet() + set.removeAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun BooleanArray.subtract(other: Iterable): Set { + val set = this.toMutableSet() + set.removeAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun ByteArray.subtract(other: Iterable): Set { + val set = this.toMutableSet() + set.removeAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun CharArray.subtract(other: Iterable): Set { + val set = this.toMutableSet() + set.removeAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun DoubleArray.subtract(other: Iterable): Set { + val set = this.toMutableSet() + set.removeAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun FloatArray.subtract(other: Iterable): Set { + val set = this.toMutableSet() + set.removeAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun IntArray.subtract(other: Iterable): Set { + val set = this.toMutableSet() + set.removeAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun LongArray.subtract(other: Iterable): Set { + val set = this.toMutableSet() + set.removeAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun ShortArray.subtract(other: Iterable): Set { + val set = this.toMutableSet() + set.removeAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun Iterable.subtract(other: Iterable): Set { + val set = this.toMutableSet() + set.removeAll(other) + return set +} + +/** + * Returns a mutable set containing all distinct elements from the given collection. + */ +public fun Array.toMutableSet(): MutableSet { + val set = LinkedHashSet(size) + for (item in this) set.add(item) + return set +} + +/** + * Returns a mutable set containing all distinct elements from the given collection. + */ +public fun BooleanArray.toMutableSet(): MutableSet { + val set = LinkedHashSet(size) + for (item in this) set.add(item) + return set +} + +/** + * Returns a mutable set containing all distinct elements from the given collection. + */ +public fun ByteArray.toMutableSet(): MutableSet { + val set = LinkedHashSet(size) + for (item in this) set.add(item) + return set +} + +/** + * Returns a mutable set containing all distinct elements from the given collection. + */ +public fun CharArray.toMutableSet(): MutableSet { + val set = LinkedHashSet(size) + for (item in this) set.add(item) + return set +} + +/** + * Returns a mutable set containing all distinct elements from the given collection. + */ +public fun DoubleArray.toMutableSet(): MutableSet { + val set = LinkedHashSet(size) + for (item in this) set.add(item) + return set +} + +/** + * Returns a mutable set containing all distinct elements from the given collection. + */ +public fun FloatArray.toMutableSet(): MutableSet { + val set = LinkedHashSet(size) + for (item in this) set.add(item) + return set +} + +/** + * Returns a mutable set containing all distinct elements from the given collection. + */ +public fun IntArray.toMutableSet(): MutableSet { + val set = LinkedHashSet(size) + for (item in this) set.add(item) + return set +} + +/** + * Returns a mutable set containing all distinct elements from the given collection. + */ +public fun LongArray.toMutableSet(): MutableSet { + val set = LinkedHashSet(size) + for (item in this) set.add(item) + return set +} + +/** + * Returns a mutable set containing all distinct elements from the given collection. + */ +public fun ShortArray.toMutableSet(): MutableSet { + val set = LinkedHashSet(size) + for (item in this) set.add(item) + return set +} + +/** + * Returns a mutable set containing all distinct elements from the given collection. + */ +public fun Iterable.toMutableSet(): MutableSet { + return when (this) { + is Collection -> LinkedHashSet(this) + else -> toCollection(LinkedHashSet()) + } +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun Array.union(other: Iterable): Set { + val set = this.toMutableSet() + set.addAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun BooleanArray.union(other: Iterable): Set { + val set = this.toMutableSet() + set.addAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun ByteArray.union(other: Iterable): Set { + val set = this.toMutableSet() + set.addAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun CharArray.union(other: Iterable): Set { + val set = this.toMutableSet() + set.addAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun DoubleArray.union(other: Iterable): Set { + val set = this.toMutableSet() + set.addAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun FloatArray.union(other: Iterable): Set { + val set = this.toMutableSet() + set.addAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun IntArray.union(other: Iterable): Set { + val set = this.toMutableSet() + set.addAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun LongArray.union(other: Iterable): Set { + val set = this.toMutableSet() + set.addAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun ShortArray.union(other: Iterable): Set { + val set = this.toMutableSet() + set.addAll(other) + return set +} + +/** + * Returns a set containing all distinct elements from both collections. + */ +public fun Iterable.union(other: Iterable): Set { + val set = this.toMutableSet() + set.addAll(other) + return set +} + diff --git a/libraries/stdlib/src/kotlin/collections/MutableCollections.kt b/libraries/stdlib/src/kotlin/collections/MutableCollections.kt index 1a99bebe612..0aa9191f8d7 100644 --- a/libraries/stdlib/src/kotlin/collections/MutableCollections.kt +++ b/libraries/stdlib/src/kotlin/collections/MutableCollections.kt @@ -3,14 +3,64 @@ package kotlin /** * Adds all elements of the given *iterable* to this [[MutableCollection]] */ -public fun MutableCollection.addAll(iterable: Iterable): Unit { - for (e in iterable) add(e) +public fun MutableCollection.addAll(iterable: Iterable) { + when (iterable) { + is Collection -> addAll(iterable) + else -> for (item in iterable) add(item) + } } -public fun MutableCollection.addAll(stream: Stream): Unit { - for (e in stream) add(e) +/** + * Adds all elements of the given *stream* to this [[MutableCollection]] + */ +public fun MutableCollection.addAll(stream: Stream) { + for (item in stream) add(item) } -public fun MutableCollection.addAll(array: Array): Unit { - for (e in array) add(e) +/** + * Adds all elements of the given *array* to this [[MutableCollection]] + */ +public fun MutableCollection.addAll(array: Array) { + for (item in array) add(item) +} + +/** + * Removes all elements of the given *iterable* from this [[MutableCollection]] + */ +public fun MutableCollection.removeAll(iterable: Iterable) { + when (iterable) { + is Collection -> removeAll(iterable) + else -> for (item in iterable) remove(item) + } +} + +/** + * Removes all elements of the given *stream* from this [[MutableCollection]] + */ +public fun MutableCollection.removeAll(stream: Stream) { + for (item in stream) remove(item) +} + +/** + * Removes all elements of the given *array* from this [[MutableCollection]] + */ +public fun MutableCollection.removeAll(array: Array) { + for (item in array) remove(item) +} + +/** + * Retains only elements of the given *iterable* in this [[MutableCollection]] + */ +public fun MutableCollection.retainAll(iterable: Iterable) { + when (iterable) { + is Collection -> retainAll(iterable) + else -> retainAll(iterable.toSet()) + } +} + +/** + * Retains only elements of the given *array* in this [[MutableCollection]] + */ +public fun MutableCollection.retainAll(array: Array) { + retainAll(array.toSet()) } diff --git a/libraries/stdlib/src/kotlin/collections/Stream.kt b/libraries/stdlib/src/kotlin/collections/Stream.kt index f1701e46c9a..357e78ff1b6 100644 --- a/libraries/stdlib/src/kotlin/collections/Stream.kt +++ b/libraries/stdlib/src/kotlin/collections/Stream.kt @@ -38,13 +38,13 @@ public class TransformingStream(val stream: Stream, val transformer: (T } } -class ZippingStream(val stream1: Stream, val stream2: Stream) : Stream> { - override fun iterator(): Iterator> = object : AbstractIterator>() { +public class MergingStream(val stream1: Stream, val stream2: Stream, val transform: (T1, T2) -> V) : Stream { + override fun iterator(): Iterator = object : AbstractIterator() { val iterator1 = stream1.iterator() val iterator2 = stream2.iterator() override fun computeNext() { if (iterator1.hasNext() && iterator2.hasNext()) { - setNext(iterator1.next() to iterator2.next()) + setNext(transform(iterator1.next(), iterator2.next())) } else { done() } diff --git a/libraries/stdlib/src/kotlin/text/StringBuilder.kt b/libraries/stdlib/src/kotlin/text/StringBuilder.kt new file mode 100644 index 00000000000..de8fffe04f6 --- /dev/null +++ b/libraries/stdlib/src/kotlin/text/StringBuilder.kt @@ -0,0 +1,37 @@ +package kotlin + +/** + * Builds newly created StringBuilder using provided body. + */ +public inline fun StringBuilder(body: StringBuilder.() -> Unit): StringBuilder { + val sb = StringBuilder() + sb.body() + return sb +} + +/** + * Appends all arguments to the given Appendable + */ +public fun T.append(vararg value: CharSequence?): T { + for (item in value) + append(item) + return this +} + +/** + * Appends all arguments to the given StringBuilder + */ +public fun StringBuilder.append(vararg value: String?): StringBuilder { + for (item in value) + append(item) + return this +} + +/** + * Appends all arguments to the given StringBuilder + */ +public fun StringBuilder.append(vararg value: Any?): StringBuilder { + for (item in value) + append(item) + return this +} diff --git a/libraries/stdlib/src/kotlin/text/StringBuilderJVM.kt b/libraries/stdlib/src/kotlin/text/StringBuilderJVM.kt new file mode 100644 index 00000000000..cf06ad96032 --- /dev/null +++ b/libraries/stdlib/src/kotlin/text/StringBuilderJVM.kt @@ -0,0 +1,59 @@ +package kotlin + +/** Line separator for current system. */ +val LINE_SEPARATOR: String = System.getProperty("line.separator")!! + +/** Appends line separator to Appendable. */ +public fun Appendable.appendln(): Appendable = append(LINE_SEPARATOR) + +/** Appends value to the given Appendable and line separator after it. */ +public fun Appendable.appendln(value: CharSequence?): Appendable = append(value).append(LINE_SEPARATOR) + +/** Appends value to the given Appendable and line separator after it. */ +public fun Appendable.appendln(value: Char): Appendable = append(value).append(LINE_SEPARATOR) + +/** Appends line separator to StringBuilder. */ + +public fun StringBuilder.appendln(): StringBuilder = append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: StringBuffer?): StringBuilder = append(value).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: CharSequence?): StringBuilder = append(value).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: String?): StringBuilder = append(value).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: Any?): StringBuilder = append(value).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: StringBuilder?): StringBuilder = append(value).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: CharArray): StringBuilder = append(value).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: Char): StringBuilder = append(value).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: Boolean): StringBuilder = append(value).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: Int): StringBuilder = append(value).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: Short): StringBuilder = append(value.toInt()).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: Byte): StringBuilder = append(value.toInt()).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: Long): StringBuilder = append(value).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: Float): StringBuilder = append(value).append(LINE_SEPARATOR) + +/** Appends value to the given StringBuilder and line separator after it. */ +public fun StringBuilder.appendln(value: Double): StringBuilder = append(value).append(LINE_SEPARATOR) diff --git a/libraries/stdlib/src/kotlin/text/Strings.kt b/libraries/stdlib/src/kotlin/text/Strings.kt index 57c44f98542..4de2122fcd9 100644 --- a/libraries/stdlib/src/kotlin/text/Strings.kt +++ b/libraries/stdlib/src/kotlin/text/Strings.kt @@ -57,11 +57,11 @@ public val String.indices: IntRange * Returns a subsequence specified by given set of indices. */ public fun CharSequence.slice(indices: Iterable): CharSequence { - val result = StringBuilder() + val sb = StringBuilder() for (i in indices) { - result.append(get(i)) + sb.append(get(i)) } - return result.toString() + return sb.toString() } /** @@ -95,3 +95,155 @@ public fun Array.join(separator: String = ", ", prefix: String = "", pos public fun Stream.join(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "..."): String { return joinToString(separator, prefix, postfix, limit, truncated) } +/** + * Returns a substring before first occurrence of delimiter. In case of no delimiter, returns the whole string. + */ +public fun String.substringBefore(delimiter: Char): String { + val index = indexOf(delimiter) + return if (index == -1) this else substring(0, index) +} + +/** + * Returns a substring before first occurrence of delimiter. In case of no delimiter, returns the whole string. + */ +public fun String.substringBefore(delimiter: String): String { + val index = indexOf(delimiter) + return if (index == -1) this else substring(0, index) +} +/** + * Returns a substring after first occurrence of delimiter. In case of no delimiter, returns an empty string. + */ +public fun String.substringAfter(delimiter: Char): String { + val index = indexOf(delimiter) + return if (index == -1) "" else substring(index + 1, length) +} + +/** + * Returns a substring after first occurrence of delimiter. In case of no delimiter, returns an empty string. + */ +public fun String.substringAfter(delimiter: String): String { + val index = indexOf(delimiter) + return if (index == -1) "" else substring(index + delimiter.length, length) +} + +/** + * Returns a substring before last occurrence of delimiter. In case of no delimiter, returns the whole string. + */ +public fun String.substringBeforeLast(delimiter: Char): String { + val index = lastIndexOf(delimiter) + return if (index == -1) this else substring(0, index) +} + +/** + * Returns a substring before last occurrence of delimiter. In case of no delimiter, returns the whole string. + */ +public fun String.substringBeforeLast(delimiter: String): String { + val index = lastIndexOf(delimiter) + return if (index == -1) this else substring(0, index) +} + +/** + * Returns a substring after last occurrence of delimiter. In case of no delimiter, returns an empty string. + */ +public fun String.substringAfterLast(delimiter: Char): String { + val index = lastIndexOf(delimiter) + return if (index == -1) "" else substring(index + 1, length) +} + +/** + * Returns a substring after last occurrence of delimiter. In case of no delimiter, returns an empty string. + */ +public fun String.substringAfterLast(delimiter: String): String { + val index = lastIndexOf(delimiter) + return if (index == -1) "" else substring(index + delimiter.length, length) +} + +/** + * Replace part of string at given range with replacement string + */ +public fun String.replaceRange(firstIndex: Int, lastIndex: Int, replacement: String): String { + if (lastIndex < firstIndex) + throw IndexOutOfBoundsException("Last index ($lastIndex) is less than first index ($firstIndex)") + val sb = StringBuilder() + sb.append(this, 0, firstIndex) + sb.append(replacement) + sb.append(this, lastIndex, length) + return sb.toString() +} + +/** + * Replace part of string at given range with replacement string + */ +public fun String.replaceRange(range: IntRange, replacement: String): String { + if (range.end < range.start) + throw IndexOutOfBoundsException("Last index (${range.start}) is less than first index (${range.end})") + val sb = StringBuilder() + sb.append(this, 0, range.start) + sb.append(replacement) + sb.append(this, range.end, length) + return sb.toString() +} + +/** + * Replace part of string before first occurrence of given delimiter with replacement string + */ +public fun String.replaceBefore(delimiter: Char, replacement: String): String { + val index = indexOf(delimiter) + return if (index == -1) replacement else replaceRange(0, index, replacement) +} + +/** + * Replace part of string before first occurrence of given delimiter with replacement string + */ +public fun String.replaceBefore(delimiter: String, replacement: String): String { + val index = indexOf(delimiter) + return if (index == -1) replacement else replaceRange(0, index, replacement) +} + +/** + * Replace part of string after first occurrence of given delimiter with replacement string + */ +public fun String.replaceAfter(delimiter: Char, replacement: String): String { + val index = indexOf(delimiter) + return if (index == -1) this else replaceRange(index + 1, length, replacement) +} + +/** + * Replace part of string after first occurrence of given delimiter with replacement string + */ +public fun String.replaceAfter(delimiter: String, replacement: String): String { + val index = indexOf(delimiter) + return if (index == -1) this else replaceRange(index + delimiter.length, length, replacement) +} + +/** + * Replace part of string after last occurrence of given delimiter with replacement string + */ +public fun String.replaceAfterLast(delimiter: String, replacement: String): String { + val index = lastIndexOf(delimiter) + return if (index == -1) this else replaceRange(index + delimiter.length, length, replacement) +} + +/** + * Replace part of string after last occurrence of given delimiter with replacement string + */ +public fun String.replaceAfterLast(delimiter: Char, replacement: String): String { + val index = lastIndexOf(delimiter) + return if (index == -1) this else replaceRange(index + 1, length, replacement) +} + +/** + * Replace part of string before last occurrence of given delimiter with replacement string + */ +public fun String.replaceBeforeLast(delimiter: Char, replacement: String): String { + val index = lastIndexOf(delimiter) + return if (index == -1) replacement else replaceRange(0, index, replacement) +} + +/** + * Replace part of string before last occurrence of given delimiter with replacement string + */ +public fun String.replaceBeforeLast(delimiter: String, replacement: String): String { + val index = lastIndexOf(delimiter) + return if (index == -1) replacement else replaceRange(0, index, replacement) +} diff --git a/libraries/stdlib/test/collections/CollectionTest.kt b/libraries/stdlib/test/collections/CollectionTest.kt index cc2627ff3f9..72ea5224722 100644 --- a/libraries/stdlib/test/collections/CollectionTest.kt +++ b/libraries/stdlib/test/collections/CollectionTest.kt @@ -120,6 +120,20 @@ class CollectionTest { } } + test + fun merge() { + expect(listOf("ab", "bc", "cd")) { + listOf("a", "b", "c").merge(listOf("b", "c", "d")) { a, b -> a + b } + } + } + + test + fun zip() { + expect(listOf("a" to "b", "b" to "c", "c" to "d")) { + listOf("a", "b", "c").zip(listOf("b", "c", "d")) + } + } + test fun partition() { val data = arrayListOf("foo", "bar", "something", "xyz") val pair = data.partition { it.size == 3 } diff --git a/libraries/stdlib/test/collections/IterableTests.kt b/libraries/stdlib/test/collections/IterableTests.kt index 10a5765bf5d..1ecee2492c6 100644 --- a/libraries/stdlib/test/collections/IterableTests.kt +++ b/libraries/stdlib/test/collections/IterableTests.kt @@ -105,7 +105,7 @@ abstract class IterableTests>(val data: T, val empty: T) { Test fun filter() { val foo = data.filter { it.startsWith("f") } - // TODO uncomment this when KT-4651 will be fixed + // TODO uncomment this when KT-2468 will be fixed //expect(true) { foo is List } expect(true) { foo.all { it.startsWith("f") } } expect(1) { foo.size } @@ -114,7 +114,7 @@ abstract class IterableTests>(val data: T, val empty: T) { Test fun filterNot() { val notFoo = data.filterNot { it.startsWith("f") } - // TODO uncomment this when KT-4651 will be fixed + // TODO uncomment this when KT-2468 will be fixed //expect(true) { notFoo is List } expect(true) { notFoo.none { it.startsWith("f") } } expect(1) { notFoo.size } diff --git a/libraries/stdlib/test/collections/MapTest.kt b/libraries/stdlib/test/collections/MapTest.kt index 43dc8cb5de1..4638138a035 100644 --- a/libraries/stdlib/test/collections/MapTest.kt +++ b/libraries/stdlib/test/collections/MapTest.kt @@ -53,7 +53,7 @@ class MapTest { assertEquals(map.size(), 1) assertEquals("James", map["name"]) } - + test fun iterate() { val map = TreeMap() map["beverage"] = "beer" diff --git a/libraries/stdlib/test/collections/SetOperationsTest.kt b/libraries/stdlib/test/collections/SetOperationsTest.kt new file mode 100644 index 00000000000..6528a3bed34 --- /dev/null +++ b/libraries/stdlib/test/collections/SetOperationsTest.kt @@ -0,0 +1,30 @@ +package test.collections + +import kotlin.test.* +import org.junit.Test as test + +class SetOperationsTest { + test fun distinct() { + assertEquals(listOf(1, 3, 5), listOf(1, 3, 3, 1, 5, 1, 3).distinct().toList()) + assertEquals(listOf(), listOf().distinct().toList()) + } + + test fun union() { + assertEquals(listOf(1, 3, 5), listOf(1, 3).union(listOf(5)).toList()) + assertEquals(listOf(1), listOf().union(listOf(1)).toList()) + } + + test fun subtract() { + assertEquals(listOf(1, 3), listOf(1, 3).subtract(listOf(5)).toList()) + assertEquals(listOf(1, 3), listOf(1, 3, 5).subtract(listOf(5)).toList()) + assertEquals(listOf(), listOf(1, 3, 5).subtract(listOf(1, 3, 5)).toList()) + assertEquals(listOf(), listOf().subtract(listOf(1)).toList()) + } + + test fun intersect() { + assertEquals(listOf(), listOf(1, 3).intersect(listOf(5)).toList()) + assertEquals(listOf(5), listOf(1, 3, 5).intersect(listOf(5)).toList()) + assertEquals(listOf(1, 3, 5), listOf(1, 3, 5).intersect(listOf(1, 3, 5)).toList()) + assertEquals(listOf(), listOf().intersect(listOf(1)).toList()) + } +} \ No newline at end of file diff --git a/libraries/stdlib/test/collections/StreamTest.kt b/libraries/stdlib/test/collections/StreamTest.kt index 1e8f6562e56..4efc8b8c3c6 100644 --- a/libraries/stdlib/test/collections/StreamTest.kt +++ b/libraries/stdlib/test/collections/StreamTest.kt @@ -9,7 +9,7 @@ fun fibonacci(): Stream { var index = 0; var a = 0; var b = 1 - return stream { + return stream { when (index++) { 0 -> a; 1 -> b; else -> { val result = a + b; a = b; b = result; result } } @@ -73,6 +73,13 @@ public class StreamTest { assertEquals("13, 21, 34, 55, 89, 144, 233, 377, 610, 987, ...", fibonacci().drop(3).drop(4).joinToString(limit = 10)) } + test + fun merge() { + expect(listOf("ab", "bc", "cd")) { + streamOf("a", "b", "c").merge(streamOf("b", "c", "d")) { a, b -> a + b }.toList() + } + } + test fun toStringJoinsNoMoreThanTheFirstTenElements() { assertEquals("0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...", fibonacci().joinToString(limit = 10)) assertEquals("13, 21, 34, 55, 89, 144, 233, 377, 610, 987, ...", fibonacci().filter { it > 10 }.joinToString(limit = 10)) @@ -81,8 +88,8 @@ public class StreamTest { test fun plus() { val stream = listOf("foo", "bar").stream() - val streamChease = stream + "cheese" - assertEquals(listOf("foo", "bar", "cheese"), streamChease.toList()) + val streamCheese = stream + "cheese" + assertEquals(listOf("foo", "bar", "cheese"), streamCheese.toList()) // lets use a mutable variable var mi = listOf("a", "b").stream() @@ -118,7 +125,7 @@ public class StreamTest { test fun streamFromFunction() { var count = 3 - val stream = stream { + val stream = stream { count-- if (count >= 0) count else null } @@ -128,7 +135,7 @@ public class StreamTest { } test fun streamFromFunctionWithInitialValue() { - val values = stream(3) { n -> if (n > 0) n - 1 else null } + val values = stream(3) { n -> if (n > 0) n - 1 else null } assertEquals(arrayListOf(3, 2, 1, 0), values.toList()) } diff --git a/libraries/stdlib/test/text/StringBuilderTest.kt b/libraries/stdlib/test/text/StringBuilderTest.kt new file mode 100644 index 00000000000..90677c70e42 --- /dev/null +++ b/libraries/stdlib/test/text/StringBuilderTest.kt @@ -0,0 +1,28 @@ +package test.text + +import kotlin.test.* +import org.junit.Test as test + +class StringBuilderTest { + + test fun stringBuild() { + val s = StringBuilder { + append("a") + append(true) + }.toString() + assertEquals("atrue", s) + } + + test fun appendMany() { + assertEquals("a1", StringBuilder().append("a", "1").toString()) + assertEquals("a1", StringBuilder().append("a", 1).toString()) + assertEquals("a1", StringBuilder().append("a", StringBuilder().append("1")).toString()) + } + + test fun append() { + // this test is needed for JS implementation + assertEquals("em", StringBuilder { + append("element", 2, 4) + }.toString()) + } +} diff --git a/libraries/stdlib/test/text/StringTest.kt b/libraries/stdlib/test/text/StringTest.kt index a1d584ec0fc..10c6b50c78f 100644 --- a/libraries/stdlib/test/text/StringTest.kt +++ b/libraries/stdlib/test/text/StringTest.kt @@ -66,6 +66,61 @@ class StringTest { test fun indices() { assertEquals(0..4, "abcde".indices) assertEquals(0..0, "a".indices) - assertEquals(IntRange.EMPTY, "".indices) + assertTrue("".indices.isEmpty()) + } + + test fun replaceRange() { + val s = "sample text" + assertEquals("sa??e text", s.replaceRange(2, 5, "??")) + assertEquals("sa??e text", s.replaceRange(2..5, "??")) + fails { + s.replaceRange(5..2, "??") + } + fails { + s.replaceRange(5, 2, "??") + } + } + + test fun substringDelimited() { + val s = "-1,22,3+" + // chars + assertEquals("22,3+", s.substringAfter(',')) + assertEquals("3+", s.substringAfterLast(',')) + assertEquals("-1", s.substringBefore(',')) + assertEquals("-1,22", s.substringBeforeLast(',')) + + // strings + assertEquals("22,3+", s.substringAfter(",")) + assertEquals("3+", s.substringAfterLast(",")) + assertEquals("-1", s.substringBefore(",")) + assertEquals("-1,22", s.substringBeforeLast(",")) + + // non-existing delimiter + assertEquals("", s.substringAfter("+")) + assertEquals("", s.substringBefore("-")) + assertEquals(s, s.substringBefore("=")) + assertEquals("", s.substringAfter("=")) + + } + + test fun replaceDelimited() { + val s = "/user/folder/file.extension" + // chars + assertEquals("/user/folder/file.doc", s.replaceAfter('.', "doc")) + assertEquals("/user/folder/another.doc", s.replaceAfterLast('/', "another.doc")) + assertEquals("new name.extension", s.replaceBefore('.', "new name")) + assertEquals("/new/path/file.extension", s.replaceBeforeLast('/', "/new/path")) + + // strings + assertEquals("/user/folder/file.doc", s.replaceAfter(".", "doc")) + assertEquals("/user/folder/another.doc", s.replaceAfterLast("/", "another.doc")) + assertEquals("new name.extension", s.replaceBefore(".", "new name")) + assertEquals("/new/path/file.extension", s.replaceBeforeLast("/", "/new/path")) + + // non-existing delimiter + assertEquals("/user/folder/file.extension", s.replaceAfter("=", "doc")) + assertEquals("/user/folder/file.extension", s.replaceAfterLast("=", "another.doc")) + assertEquals("new name", s.replaceBefore("=", "new name")) + assertEquals("/new/path", s.replaceBeforeLast("=", "/new/path")) } } diff --git a/libraries/stdlib/test/text/StringUtilTest.kt b/libraries/stdlib/test/text/StringUtilTest.kt index 3998aaeedd7..5414c3dc515 100644 --- a/libraries/stdlib/test/text/StringUtilTest.kt +++ b/libraries/stdlib/test/text/StringUtilTest.kt @@ -3,14 +3,12 @@ package test.text import kotlin.* import kotlin.test.* import kotlin.util.* +import org.junit.Test as test -import junit.framework.* - -class StringUtilTest() : TestCase() { - - fun testToRegex() { +class StringUtilTest() { + test fun toRegex() { val re = """foo""".toRegex() val list = re.split("hellofoobar").toList() - assertEquals(arrayList("hello", "bar"), list) + assertEquals(listOf("hello", "bar"), list) } } diff --git a/libraries/tools/kotlin-js-library/pom.xml b/libraries/tools/kotlin-js-library/pom.xml index 01c94c1834f..6d90531bcd6 100644 --- a/libraries/tools/kotlin-js-library/pom.xml +++ b/libraries/tools/kotlin-js-library/pom.xml @@ -71,6 +71,7 @@ --> + diff --git a/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateCollections.kt b/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateCollections.kt index 2e43193bbd4..bc4deb906ad 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateCollections.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateCollections.kt @@ -12,6 +12,7 @@ fun generateCollectionsAPI(outDir: File) { arrays().writeTo(File(outDir, "_Arrays.kt")) { build() } snapshots().writeTo(File(outDir, "_Snapshots.kt")) { build() } mapping().writeTo(File(outDir, "_Mapping.kt")) { build() } + sets().writeTo(File(outDir, "_Sets.kt")) { build() } aggregates().writeTo(File(outDir, "_Aggregates.kt")) { build() } guards().writeTo(File(outDir, "_Guards.kt")) { build() } generators().writeTo(File(outDir, "_Generators.kt")) { build() } diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Generators.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Generators.kt index 3d1cb6599c6..1345cff7f72 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Generators.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Generators.kt @@ -118,6 +118,73 @@ fun generators(): List { } } + templates add f("merge(other: Iterable, transform: (T, R) -> V)") { + exclude(Streams) + doc { + """ + Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + """ + } + typeParam("R") + typeParam("V") + returns("List") + inline(true) + body { + """ + val first = iterator() + val second = other.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list + """ + } + } + + templates add f("merge(array: Array, transform: (T, R) -> V)") { + exclude(Streams) + doc { + """ + Returns a list of values built from elements of both collections with same indexes using provided *transform*. List has length of shortest collection. + """ + } + typeParam("R") + typeParam("V") + returns("List") + inline(true) + body { + """ + val first = iterator() + val second = array.iterator() + val list = arrayListOf() + while (first.hasNext() && second.hasNext()) { + list.add(transform(first.next(), second.next())) + } + return list + """ + } + } + + + templates add f("merge(stream: Stream, transform: (T, R) -> V)") { + only(Streams) + doc { + """ + Returns a stream of values built from elements of both collections with same indexes using provided *transform*. Stream has length of shortest stream. + """ + } + typeParam("R") + typeParam("V") + returns("Stream") + body { + """ + return MergingStream(this, stream, transform) + """ + } + } + + templates add f("zip(other: Iterable)") { exclude(Streams) doc { @@ -129,13 +196,7 @@ fun generators(): List { returns("List>") body { """ - val first = iterator() - val second = other.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(other) { (t1, t2) -> t1 to t2 } """ } } @@ -172,13 +233,7 @@ fun generators(): List { returns("List>") body { """ - val first = iterator() - val second = array.iterator() - val list = ArrayList>() - while (first.hasNext() && second.hasNext()) { - list.add(first.next() to second.next()) - } - return list + return merge(array) { (t1, t2) -> t1 to t2 } """ } } @@ -187,14 +242,14 @@ fun generators(): List { only(Streams) doc { """ - Returns a stream of pairs built from elements of both collections with same indexes. List has length of shortest collection. + Returns a stream of pairs built from elements of both collections with same indexes. Stream has length of shortest stream. """ } typeParam("R") returns("Stream>") body { """ - return ZippingStream(this, stream) + return MergingStream(this, stream) { (t1, t2) -> t1 to t2 } """ } } diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Sets.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Sets.kt new file mode 100644 index 00000000000..6009f4535ec --- /dev/null +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Sets.kt @@ -0,0 +1,81 @@ +package templates + +import templates.Family.* + +fun sets(): List { + val templates = arrayListOf() + + templates add f("toMutableSet()") { + exclude(Strings, Streams) + doc { "Returns a mutable set containing all distinct elements from the given collection." } + returns("MutableSet") + body { + """ + return when (this) { + is Collection -> LinkedHashSet(this) + else -> toCollection(LinkedHashSet()) + } + """ + } + body(ArraysOfObjects, ArraysOfPrimitives) { + """ + val set = LinkedHashSet(size) + for (item in this) set.add(item) + return set + """ + } + } + + templates add f("distinct()") { + exclude(Strings, Streams) + doc { "Returns a set containing all distinct elements from the given collection." } + + returns("Set") + body { + """ + return this.toMutableSet() + """ + } + } + + templates add f("union(other: Iterable)") { + exclude(Strings, Streams) + doc { "Returns a set containing all distinct elements from both collections." } + returns("Set") + body { + """ + val set = this.toMutableSet() + set.addAll(other) + return set + """ + } + } + + templates add f("intersect(other: Iterable)") { + exclude(Strings, Streams) + doc { "Returns a set containing all distinct elements from both collections." } + returns("Set") + body { + """ + val set = this.toMutableSet() + set.retainAll(other) + return set + """ + } + } + + templates add f("subtract(other: Iterable)") { + exclude(Strings, Streams) + doc { "Returns a set containing all distinct elements from both collections." } + returns("Set") + body { + """ + val set = this.toMutableSet() + set.removeAll(other) + return set + """ + } + } + + return templates +} \ No newline at end of file