Merge master into idea14
Conflicts: .idea/runConfigurations/All_Tests.xml idea/src/org/jetbrains/jet/plugin/conversion/copy/ConvertJavaCopyPastePostProcessor.kt idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/AbstractJetExtractionTest.kt idea/tests/org/jetbrains/jet/shortenRefs/AbstractShortenRefsTest.kt
This commit is contained in:
Generated
+1
@@ -22,6 +22,7 @@
|
||||
<value defaultName="moduleWithDependencies" />
|
||||
</option>
|
||||
<envs>
|
||||
<env name="kotlin.tests.actually.compile" value="true" />
|
||||
<env name="NO_FS_ROOTS_ACCESS_CHECK" value="true" />
|
||||
</envs>
|
||||
<patterns />
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<root>
|
||||
<item name='com.intellij.codeInsight.CodeInsightSettings com.intellij.codeInsight.CodeInsightSettings getInstance()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
@@ -2,4 +2,8 @@
|
||||
<item name='com.intellij.lang.ASTNode java.lang.String getText()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.lang.SmartEnterProcessorWithFixers.FixEnterProcessor boolean doEnter(com.intellij.psi.PsiElement, com.intellij.psi.PsiFile, com.intellij.openapi.editor.Editor, boolean) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
@@ -474,6 +474,16 @@
|
||||
void stop();
|
||||
void dispose();
|
||||
}
|
||||
|
||||
-keepclassmembers class org.jetbrains.org.objectweb.asm.Opcodes {
|
||||
*** ASM5;
|
||||
}
|
||||
|
||||
-keepclassmembers class org.jetbrains.org.objectweb.asm.ClassReader {
|
||||
*** SKIP_CODE;
|
||||
*** SKIP_DEBUG;
|
||||
*** SKIP_FRAMES;
|
||||
}
|
||||
]]></proguard>
|
||||
</else>
|
||||
</if>
|
||||
|
||||
@@ -85,7 +85,10 @@ public abstract class AnnotationCodegen {
|
||||
bindingContext = typeMapper.getBindingContext();
|
||||
}
|
||||
|
||||
public void genAnnotations(Annotated annotated) {
|
||||
/**
|
||||
* @param returnType can be null if not applicable (e.g. {@code annotated} is a class)
|
||||
*/
|
||||
public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType) {
|
||||
if (annotated == null) {
|
||||
return;
|
||||
}
|
||||
@@ -111,7 +114,7 @@ public abstract class AnnotationCodegen {
|
||||
}
|
||||
|
||||
if (modifierList == null) {
|
||||
generateAdditionalAnnotations(annotated, Collections.<String>emptySet());
|
||||
generateAdditionalAnnotations(annotated, returnType, Collections.<String>emptySet());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -131,10 +134,14 @@ public abstract class AnnotationCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
generateAdditionalAnnotations(annotated, annotationDescriptorsAlreadyPresent);
|
||||
generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent);
|
||||
}
|
||||
|
||||
private void generateAdditionalAnnotations(@NotNull Annotated annotated, @NotNull Set<String> annotationDescriptorsAlreadyPresent) {
|
||||
private void generateAdditionalAnnotations(
|
||||
@NotNull Annotated annotated,
|
||||
@Nullable Type returnType,
|
||||
@NotNull Set<String> annotationDescriptorsAlreadyPresent
|
||||
) {
|
||||
if (annotated instanceof CallableDescriptor) {
|
||||
CallableDescriptor descriptor = (CallableDescriptor) annotated;
|
||||
|
||||
@@ -142,7 +149,9 @@ public abstract class AnnotationCodegen {
|
||||
if (isInvisibleFromTheOutside(descriptor)) return;
|
||||
if (descriptor instanceof ValueParameterDescriptor && isInvisibleFromTheOutside(descriptor.getContainingDeclaration())) return;
|
||||
|
||||
generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
|
||||
if (returnType != null && !AsmUtil.isPrimitive(returnType)) {
|
||||
generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +175,6 @@ public abstract class AnnotationCodegen {
|
||||
}
|
||||
|
||||
boolean isNullableType = JvmCodegenUtil.isNullableType(type);
|
||||
if (!isNullableType && KotlinBuiltIns.getInstance().isPrimitiveType(type)) return;
|
||||
|
||||
Class<?> annotationClass = isNullableType ? Nullable.class : NotNull.class;
|
||||
|
||||
|
||||
@@ -722,7 +722,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
invokeFunction(fakeCall, StackValue.local(iteratorVarIndex, asmTypeForIterator), hasNextCall);
|
||||
|
||||
JetType type = hasNextCall.getResultingDescriptor().getReturnType();
|
||||
assert type != null && JetTypeChecker.INSTANCE.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType());
|
||||
assert type != null && JetTypeChecker.DEFAULT.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType());
|
||||
|
||||
Type asmType = asmType(type);
|
||||
StackValue.coerce(asmType, Type.BOOLEAN_TYPE, v);
|
||||
@@ -3413,6 +3413,11 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
|
||||
myFrameMap.leave(descriptor);
|
||||
|
||||
Label clauseEnd = new Label();
|
||||
v.mark(clauseEnd);
|
||||
|
||||
v.visitLocalVariable(descriptor.getName().asString(), descriptorType.getDescriptor(), null, clauseStart, clauseEnd, index);
|
||||
|
||||
genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null);
|
||||
|
||||
generateExceptionTable(clauseStart, tryBlockRegions, descriptorType.getInternalName());
|
||||
|
||||
@@ -143,7 +143,7 @@ public class FunctionCodegen extends ParentCodegenAware {
|
||||
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
|
||||
}
|
||||
|
||||
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor);
|
||||
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, asmMethod.getReturnType());
|
||||
|
||||
generateParameterAnnotations(functionDescriptor, mv, jvmSignature);
|
||||
|
||||
@@ -180,7 +180,8 @@ public class FunctionCodegen extends ParentCodegenAware {
|
||||
List<JvmMethodParameterSignature> kotlinParameterTypes = jvmSignature.getValueParameters();
|
||||
|
||||
for (int i = 0; i < kotlinParameterTypes.size(); i++) {
|
||||
JvmMethodParameterKind kind = kotlinParameterTypes.get(i).getKind();
|
||||
JvmMethodParameterSignature parameterSignature = kotlinParameterTypes.get(i);
|
||||
JvmMethodParameterKind kind = parameterSignature.getKind();
|
||||
if (kind.isSkippedInGenericSignature()) {
|
||||
markEnumOrInnerConstructorParameterAsSynthetic(mv, i);
|
||||
continue;
|
||||
@@ -189,7 +190,7 @@ public class FunctionCodegen extends ParentCodegenAware {
|
||||
if (kind == JvmMethodParameterKind.VALUE) {
|
||||
ValueParameterDescriptor parameter = iterator.next();
|
||||
v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i);
|
||||
AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter);
|
||||
AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter, parameterSignature.getAsmType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmClassSignature;
|
||||
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterKind;
|
||||
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignature;
|
||||
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
@@ -67,10 +66,7 @@ import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.DelegationToTraitImpl;
|
||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
|
||||
import static org.jetbrains.jet.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
|
||||
import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
|
||||
@@ -78,6 +74,9 @@ import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
|
||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
|
||||
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
|
||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.DelegationToTraitImpl;
|
||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
|
||||
import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
@@ -208,7 +207,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
writeInnerClasses();
|
||||
|
||||
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor);
|
||||
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -485,7 +484,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
JetType returnType = function.getReturnType();
|
||||
assert returnType != null : function.toString();
|
||||
JetType paramType = function.getValueParameters().get(0).getType();
|
||||
if (JetTypeChecker.INSTANCE.equalTypes(arrayType, returnType) && JetTypeChecker.INSTANCE.equalTypes(arrayType, paramType)) {
|
||||
if (JetTypeChecker.DEFAULT.equalTypes(arrayType, returnType) && JetTypeChecker.DEFAULT.equalTypes(arrayType, paramType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1083,11 +1082,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
for (PropertyAndDefaultValue info : classObjectPropertiesToCopy) {
|
||||
PropertyDescriptor property = info.descriptor;
|
||||
|
||||
Type type = typeMapper.mapType(property);
|
||||
FieldVisitor fv = v.newField(OtherOrigin(property), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, context.getFieldName(property, false),
|
||||
typeMapper.mapType(property).getDescriptor(), typeMapper.mapFieldSignature(property.getType()),
|
||||
type.getDescriptor(), typeMapper.mapFieldSignature(property.getType()),
|
||||
info.defaultValue);
|
||||
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property);
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property, type);
|
||||
|
||||
//This field are always static and final so if it has constant initializer don't do anything in clinit,
|
||||
//field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4
|
||||
|
||||
@@ -145,18 +145,15 @@ public class PropertyCodegen {
|
||||
return false;
|
||||
}
|
||||
|
||||
FieldVisitor fv;
|
||||
if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
|
||||
fv = generateBackingFieldAccess(p, descriptor);
|
||||
generateBackingFieldAccess(p, descriptor);
|
||||
}
|
||||
else if (p instanceof JetProperty && ((JetProperty) p).hasDelegate()) {
|
||||
fv = generatePropertyDelegateAccess((JetProperty) p, descriptor);
|
||||
generatePropertyDelegateAccess((JetProperty) p, descriptor);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -172,7 +169,7 @@ public class PropertyCodegen {
|
||||
if (!isTrait(context.getContextDescriptor()) || kind == OwnerKind.TRAIT_IMPL) {
|
||||
int flags = ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC;
|
||||
MethodVisitor mv = v.newMethod(OtherOrigin(descriptor), flags, name, desc, null, null);
|
||||
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(descriptor);
|
||||
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(descriptor, Type.VOID_TYPE);
|
||||
mv.visitCode();
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
mv.visitEnd();
|
||||
@@ -187,7 +184,7 @@ public class PropertyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private FieldVisitor generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) {
|
||||
private void generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) {
|
||||
int modifiers = getDeprecatedAccessFlag(propertyDescriptor);
|
||||
|
||||
for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.FIELD_FLAGS) {
|
||||
@@ -230,21 +227,22 @@ public class PropertyCodegen {
|
||||
|
||||
v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, Pair.create(type, name));
|
||||
|
||||
return builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
|
||||
typeMapper.mapFieldSignature(jetType), defaultValue);
|
||||
FieldVisitor fv = builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
|
||||
typeMapper.mapFieldSignature(jetType), defaultValue);
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(propertyDescriptor, type);
|
||||
}
|
||||
|
||||
private FieldVisitor generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||
private void generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||
JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, p.getDelegateExpression());
|
||||
if (delegateType == null) {
|
||||
// If delegate expression is unresolved reference
|
||||
delegateType = ErrorUtils.createErrorType("Delegate type");
|
||||
}
|
||||
|
||||
return generateBackingField(p, propertyDescriptor, true, delegateType, null);
|
||||
generateBackingField(p, propertyDescriptor, true, delegateType, null);
|
||||
}
|
||||
|
||||
private FieldVisitor generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) {
|
||||
private void generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) {
|
||||
Object value = null;
|
||||
|
||||
if (shouldWriteFieldInitializer(propertyDescriptor)) {
|
||||
@@ -254,7 +252,7 @@ public class PropertyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
return generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value);
|
||||
generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value);
|
||||
}
|
||||
|
||||
private boolean shouldWriteFieldInitializer(@NotNull PropertyDescriptor descriptor) {
|
||||
|
||||
@@ -446,8 +446,7 @@ public class JetTypeMapper {
|
||||
invokeOpcode = INVOKEINTERFACE;
|
||||
}
|
||||
else {
|
||||
boolean isPrivateFunInvocation = isCallInsideSameClassAsDeclared(functionDescriptor, context) &&
|
||||
functionDescriptor.getVisibility() == Visibilities.PRIVATE;
|
||||
boolean isPrivateFunInvocation = functionDescriptor.getVisibility() == Visibilities.PRIVATE;
|
||||
invokeOpcode = superCall || isPrivateFunInvocation ? INVOKESPECIAL : INVOKEVIRTUAL;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
+2
-2
@@ -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(),
|
||||
|
||||
+27
-4
@@ -16,10 +16,8 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.java.structure.impl;
|
||||
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiCompiledElement;
|
||||
import com.intellij.psi.PsiTypeParameter;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiSubstitutorImpl;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -30,7 +28,9 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.*;
|
||||
|
||||
@@ -181,4 +181,27 @@ public class JavaClassImpl extends JavaClassifierImpl<PsiClass> implements JavaC
|
||||
return OriginKind.SOURCE;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JavaType createImmediateType(@NotNull JavaTypeSubstitutor substitutor) {
|
||||
return new JavaClassifierTypeImpl(
|
||||
JavaPsiFacade.getElementFactory(getPsi().getProject()).createType(getPsi(), createPsiSubstitutor(substitutor)));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiSubstitutor createPsiSubstitutor(@NotNull JavaTypeSubstitutor substitutor) {
|
||||
Map<PsiTypeParameter, PsiType> substMap = new HashMap<PsiTypeParameter, PsiType>();
|
||||
for (Map.Entry<JavaTypeParameter, JavaType> entry : substitutor.getSubstitutionMap().entrySet()) {
|
||||
PsiTypeParameter key = ((JavaTypeParameterImpl) entry.getKey()).getPsi();
|
||||
if (entry.getValue() == null) {
|
||||
substMap.put(key, null);
|
||||
}
|
||||
else {
|
||||
substMap.put(key, ((JavaTypeImpl) entry.getValue()).getPsi());
|
||||
}
|
||||
}
|
||||
|
||||
return PsiSubstitutorImpl.createSubstitutor(substMap);
|
||||
}
|
||||
}
|
||||
|
||||
+16
-12
@@ -16,20 +16,12 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.java.structure.impl;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiClassType;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifier;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifierType;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeSubstitutor;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.types;
|
||||
|
||||
@@ -68,13 +60,25 @@ public class JavaClassifierTypeImpl extends JavaTypeImpl<PsiClassType> implement
|
||||
if (resolutionResult == null) {
|
||||
PsiClassType.ClassResolveResult result = getPsi().resolveGenerics();
|
||||
PsiClass psiClass = result.getElement();
|
||||
PsiSubstitutor substitutor = result.getSubstitutor();
|
||||
resolutionResult = new ResolutionResult(
|
||||
psiClass == null ? null : JavaClassifierImpl.create(psiClass),
|
||||
new JavaTypeSubstitutorImpl(result.getSubstitutor())
|
||||
new JavaTypeSubstitutorImpl(convertSubstitutionMap(substitutor.getSubstitutionMap()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Map<JavaTypeParameter, JavaType> convertSubstitutionMap(@NotNull Map<PsiTypeParameter, PsiType> psiMap) {
|
||||
Map<JavaTypeParameter, JavaType> substitutionMap = new HashMap<JavaTypeParameter, JavaType>();
|
||||
for (Map.Entry<PsiTypeParameter, PsiType> entry : psiMap.entrySet()) {
|
||||
PsiType value = entry.getValue();
|
||||
substitutionMap.put(new JavaTypeParameterImpl(entry.getKey()), value == null ? null : JavaTypeImpl.create(value));
|
||||
}
|
||||
|
||||
return substitutionMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Collection<JavaClassifierType> getSupertypes() {
|
||||
|
||||
+5
-5
@@ -39,31 +39,31 @@ public abstract class JavaTypeImpl<Psi extends PsiType> implements JavaType {
|
||||
return psiType.accept(new PsiTypeVisitor<JavaTypeImpl<?>>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public JavaTypeImpl<?> visitType(PsiType type) {
|
||||
public JavaTypeImpl<?> visitType(@NotNull PsiType type) {
|
||||
throw new UnsupportedOperationException("Unsupported PsiType: " + type);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JavaTypeImpl<?> visitPrimitiveType(PsiPrimitiveType primitiveType) {
|
||||
public JavaTypeImpl<?> visitPrimitiveType(@NotNull PsiPrimitiveType primitiveType) {
|
||||
return new JavaPrimitiveTypeImpl(primitiveType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JavaTypeImpl<?> visitArrayType(PsiArrayType arrayType) {
|
||||
public JavaTypeImpl<?> visitArrayType(@NotNull PsiArrayType arrayType) {
|
||||
return new JavaArrayTypeImpl(arrayType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JavaTypeImpl<?> visitClassType(PsiClassType classType) {
|
||||
public JavaTypeImpl<?> visitClassType(@NotNull PsiClassType classType) {
|
||||
return new JavaClassifierTypeImpl(classType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JavaTypeImpl<?> visitWildcardType(PsiWildcardType wildcardType) {
|
||||
public JavaTypeImpl<?> visitWildcardType(@NotNull PsiWildcardType wildcardType) {
|
||||
return new JavaWildcardTypeImpl(wildcardType);
|
||||
}
|
||||
});
|
||||
|
||||
+20
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
+128
-41
@@ -16,83 +16,170 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.java.structure.impl;
|
||||
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.PsiTypeParameter;
|
||||
import com.intellij.psi.impl.PsiSubstitutorImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeParameter;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeSubstitutor;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class JavaTypeSubstitutorImpl implements JavaTypeSubstitutor {
|
||||
private final PsiSubstitutor psiSubstitutor;
|
||||
private Map<JavaTypeParameter, JavaType> substitutionMap;
|
||||
private final Map<JavaTypeParameter, JavaType> substitutionMap;
|
||||
|
||||
public JavaTypeSubstitutorImpl(@NotNull PsiSubstitutor psiSubstitutor) {
|
||||
this.psiSubstitutor = psiSubstitutor;
|
||||
}
|
||||
|
||||
public JavaTypeSubstitutorImpl(@NotNull PsiSubstitutor psiSubstitutor, @NotNull Map<JavaTypeParameter, JavaType> substitutionMap) {
|
||||
this(psiSubstitutor);
|
||||
public JavaTypeSubstitutorImpl(@NotNull Map<JavaTypeParameter, JavaType> substitutionMap) {
|
||||
this.substitutionMap = substitutionMap;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JavaTypeSubstitutor create(@NotNull Map<JavaTypeParameter, JavaType> substitutionMap) {
|
||||
Map<PsiTypeParameter, PsiType> psiMap = new HashMap<PsiTypeParameter, PsiType>();
|
||||
for (Map.Entry<JavaTypeParameter, JavaType> entry : substitutionMap.entrySet()) {
|
||||
JavaTypeImpl value = ((JavaTypeImpl) entry.getValue());
|
||||
psiMap.put(((JavaTypeParameterImpl) entry.getKey()).getPsi(), value == null ? null : value.getPsi());
|
||||
}
|
||||
PsiSubstitutor psiSubstitutor = PsiSubstitutorImpl.createSubstitutor(psiMap);
|
||||
return new JavaTypeSubstitutorImpl(psiSubstitutor, substitutionMap);
|
||||
@Override
|
||||
public JavaType substitute(@NotNull JavaType type) {
|
||||
JavaType substitutedType = substituteInternal(type);
|
||||
return substitutedType != null ? substitutedType : correctSubstitutionForRawType(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JavaType substitute(@NotNull JavaType type) {
|
||||
return JavaTypeImpl.create(psiSubstitutor.substitute(((JavaTypeImpl) type).getPsi()));
|
||||
// In case of raw type we get substition map like T -> null,
|
||||
// in this case we should substitute upper bound of T or,
|
||||
// if it does not exist, return java.lang.Object
|
||||
private JavaType correctSubstitutionForRawType(@NotNull JavaType original) {
|
||||
if (original instanceof JavaClassifierType) {
|
||||
JavaClassifier classifier = ((JavaClassifierType) original).getClassifier();
|
||||
if (classifier instanceof JavaTypeParameter) {
|
||||
return rawTypeForTypeParameter((JavaTypeParameter) classifier);
|
||||
}
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JavaType substituteInternal(@NotNull JavaType type) {
|
||||
if (type instanceof JavaClassifierType) {
|
||||
JavaClassifierType classifierType = (JavaClassifierType) type;
|
||||
JavaClassifier classifier = classifierType.getClassifier();
|
||||
|
||||
if (classifier instanceof JavaTypeParameter) {
|
||||
return substitute((JavaTypeParameter) classifier);
|
||||
}
|
||||
else if (classifier instanceof JavaClass) {
|
||||
JavaClass javaClass = (JavaClass) classifier;
|
||||
Map<JavaTypeParameter, JavaType> substMap = new HashMap<JavaTypeParameter, JavaType>();
|
||||
processClass(javaClass, classifierType.getSubstitutor(), substMap);
|
||||
|
||||
return javaClass.createImmediateType(new JavaTypeSubstitutorImpl(substMap));
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
else if (type instanceof JavaPrimitiveType) {
|
||||
return type;
|
||||
}
|
||||
else if (type instanceof JavaArrayType) {
|
||||
JavaType componentType = ((JavaArrayType) type).getComponentType();
|
||||
JavaType substitutedComponentType = substitute(componentType);
|
||||
if (substitutedComponentType == componentType) return type;
|
||||
|
||||
return substitutedComponentType.createArrayType();
|
||||
}
|
||||
else if (type instanceof JavaWildcardType) {
|
||||
return substituteWildcardType((JavaWildcardType) type);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
private void processClass(@NotNull JavaClass javaClass, @NotNull JavaTypeSubstitutor substitutor, @NotNull Map<JavaTypeParameter, JavaType> substMap) {
|
||||
List<JavaTypeParameter> typeParameters = javaClass.getTypeParameters();
|
||||
for (JavaTypeParameter typeParameter : typeParameters) {
|
||||
JavaType substitutedParam = substitutor.substitute(typeParameter);
|
||||
if (substitutedParam == null) {
|
||||
substMap.put(typeParameter, null);
|
||||
}
|
||||
else {
|
||||
substMap.put(typeParameter, substituteInternal(substitutedParam));
|
||||
}
|
||||
}
|
||||
|
||||
if (javaClass.isStatic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
JavaClass outerClass = javaClass.getOuterClass();
|
||||
if (outerClass != null) {
|
||||
processClass(outerClass, substitutor, substMap);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JavaType substituteWildcardType(@NotNull JavaWildcardType wildcardType) {
|
||||
JavaType bound = wildcardType.getBound();
|
||||
if (bound == null) {
|
||||
return wildcardType;
|
||||
}
|
||||
|
||||
JavaType newBound = substituteInternal(bound);
|
||||
if (newBound == null) {
|
||||
// This can be in case of substitution wildcard to raw type
|
||||
return null;
|
||||
}
|
||||
|
||||
return rebound(wildcardType, newBound);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JavaWildcardType rebound(@NotNull JavaWildcardType type, @NotNull JavaType newBound) {
|
||||
if (type.getTypeProvider().createJavaLangObjectType().equals(newBound)) {
|
||||
return type.getTypeProvider().createUnboundedWildcard();
|
||||
}
|
||||
|
||||
if (type.isExtends()) {
|
||||
return type.getTypeProvider().createUpperBoundWildcard(newBound);
|
||||
}
|
||||
else {
|
||||
return type.getTypeProvider().createLowerBoundWildcard(newBound);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JavaType rawTypeForTypeParameter(@NotNull JavaTypeParameter typeParameter) {
|
||||
Collection<JavaClassifierType> bounds = typeParameter.getUpperBounds();
|
||||
if (!bounds.isEmpty()) {
|
||||
return substitute(bounds.iterator().next());
|
||||
}
|
||||
|
||||
return typeParameter.getTypeProvider().createJavaLangObjectType();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JavaType substitute(@NotNull JavaTypeParameter typeParameter) {
|
||||
PsiType psiType = psiSubstitutor.substitute(((JavaTypeParameterImpl) typeParameter).getPsi());
|
||||
return psiType == null ? null : JavaTypeImpl.create(psiType);
|
||||
if (substitutionMap.containsKey(typeParameter)) {
|
||||
return substitutionMap.get(typeParameter);
|
||||
}
|
||||
|
||||
return typeParameter.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Map<JavaTypeParameter, JavaType> getSubstitutionMap() {
|
||||
if (substitutionMap == null) {
|
||||
Map<PsiTypeParameter, PsiType> psiMap = psiSubstitutor.getSubstitutionMap();
|
||||
substitutionMap = new HashMap<JavaTypeParameter, JavaType>();
|
||||
for (Map.Entry<PsiTypeParameter, PsiType> entry : psiMap.entrySet()) {
|
||||
PsiType value = entry.getValue();
|
||||
substitutionMap.put(new JavaTypeParameterImpl(entry.getKey()), value == null ? null : JavaTypeImpl.create(value));
|
||||
}
|
||||
}
|
||||
|
||||
return substitutionMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return psiSubstitutor.hashCode();
|
||||
return substitutionMap.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof JavaTypeSubstitutorImpl && psiSubstitutor.equals(((JavaTypeSubstitutorImpl) obj).psiSubstitutor);
|
||||
return obj instanceof JavaTypeSubstitutorImpl && substitutionMap.equals(((JavaTypeSubstitutorImpl) obj).substitutionMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + ": " + psiSubstitutor;
|
||||
return getClass().getSimpleName() + ": " + substitutionMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,8 +44,8 @@ public class CheckerTestUtil {
|
||||
public int compare(@NotNull Diagnostic o1, @NotNull Diagnostic o2) {
|
||||
List<TextRange> ranges1 = o1.getTextRanges();
|
||||
List<TextRange> ranges2 = o2.getTextRanges();
|
||||
if (ranges1.size() != ranges2.size()) return ranges1.size() - ranges2.size();
|
||||
for (int i = 0; i < ranges1.size(); i++) {
|
||||
int minNumberOfRanges = ranges1.size() < ranges2.size() ? ranges1.size() : ranges2.size();
|
||||
for (int i = 0; i < minNumberOfRanges; i++) {
|
||||
TextRange range1 = ranges1.get(i);
|
||||
TextRange range2 = ranges2.get(i);
|
||||
int startOffset1 = range1.getStartOffset();
|
||||
@@ -61,7 +61,7 @@ public class CheckerTestUtil {
|
||||
return endOffset2 - endOffset1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return ranges1.size() - ranges2.size();
|
||||
}
|
||||
};
|
||||
private static final Pattern RANGE_START_OR_END_PATTERN = Pattern.compile("(<!\\w+(,\\s*\\w+)*!>)|(<!>)");
|
||||
@@ -439,41 +439,39 @@ public class CheckerTestUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static List<DiagnosticDescriptor> getSortedDiagnosticDescriptors(Collection<Diagnostic> diagnostics) {
|
||||
List<Diagnostic> list = Lists.newArrayList(diagnostics);
|
||||
Collections.sort(list, DIAGNOSTIC_COMPARATOR);
|
||||
|
||||
List<DiagnosticDescriptor> diagnosticDescriptors = Lists.newArrayList();
|
||||
DiagnosticDescriptor currentDiagnosticDescriptor = null;
|
||||
for (Diagnostic diagnostic : list) {
|
||||
List<TextRange> textRanges = diagnostic.getTextRanges();
|
||||
@NotNull
|
||||
private static List<DiagnosticDescriptor> getSortedDiagnosticDescriptors(@NotNull Collection<Diagnostic> diagnostics) {
|
||||
LinkedListMultimap<TextRange, Diagnostic> diagnosticsGroupedByRanges = LinkedListMultimap.create();
|
||||
for (Diagnostic diagnostic : diagnostics) {
|
||||
if (!diagnostic.isValid()) continue;
|
||||
|
||||
TextRange textRange = textRanges.get(0);
|
||||
if (currentDiagnosticDescriptor != null && currentDiagnosticDescriptor.equalRange(textRange)) {
|
||||
currentDiagnosticDescriptor.diagnostics.add(diagnostic);
|
||||
}
|
||||
else {
|
||||
currentDiagnosticDescriptor = new DiagnosticDescriptor(textRange.getStartOffset(), textRange.getEndOffset(), diagnostic);
|
||||
diagnosticDescriptors.add(currentDiagnosticDescriptor);
|
||||
for (TextRange textRange : diagnostic.getTextRanges()) {
|
||||
diagnosticsGroupedByRanges.put(textRange, diagnostic);
|
||||
}
|
||||
}
|
||||
List<DiagnosticDescriptor> diagnosticDescriptors = Lists.newArrayList();
|
||||
for (TextRange range : diagnosticsGroupedByRanges.keySet()) {
|
||||
diagnosticDescriptors.add(
|
||||
new DiagnosticDescriptor(range.getStartOffset(), range.getEndOffset(), diagnosticsGroupedByRanges.get(range)));
|
||||
}
|
||||
Collections.sort(diagnosticDescriptors, new Comparator<DiagnosticDescriptor>() {
|
||||
@Override
|
||||
public int compare(DiagnosticDescriptor d1, DiagnosticDescriptor d2) {
|
||||
// Start early -- go first; start at the same offset, the one who end later is the outer, i.e. goes first
|
||||
return (d1.start != d2.start) ? d1.start - d2.start : d2.end - d1.end;
|
||||
}
|
||||
});
|
||||
return diagnosticDescriptors;
|
||||
}
|
||||
|
||||
private static class DiagnosticDescriptor {
|
||||
private final int start;
|
||||
private final int end;
|
||||
private final List<Diagnostic> diagnostics = Lists.newArrayList();
|
||||
private final List<Diagnostic> diagnostics;
|
||||
|
||||
DiagnosticDescriptor(int start, int end, Diagnostic diagnostic) {
|
||||
DiagnosticDescriptor(int start, int end, List<Diagnostic> diagnostics) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.diagnostics.add(diagnostic);
|
||||
}
|
||||
|
||||
public boolean equalRange(TextRange textRange) {
|
||||
return start == textRange.getStartOffset() && end == textRange.getEndOffset();
|
||||
this.diagnostics = diagnostics;
|
||||
}
|
||||
|
||||
public Multiset<String> getDiagnosticTypeStrings() {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -124,8 +124,12 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
|
||||
public void checkFunction(@Nullable JetType expectedReturnType) {
|
||||
UnreachableCode unreachableCode = collectUnreachableCode();
|
||||
reportUnreachableCode(unreachableCode);
|
||||
|
||||
checkDefiniteReturn(expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE);
|
||||
if (subroutine instanceof JetFunctionLiteral) return;
|
||||
|
||||
checkDefiniteReturn(expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE, unreachableCode);
|
||||
|
||||
markTailCalls();
|
||||
}
|
||||
@@ -195,7 +199,7 @@ public class JetFlowInformationProvider {
|
||||
JetElement element = localDeclarationInstruction.getElement();
|
||||
if (element instanceof JetDeclarationWithBody) {
|
||||
JetDeclarationWithBody localDeclaration = (JetDeclarationWithBody) element;
|
||||
if (localDeclaration instanceof JetFunctionLiteral) continue;
|
||||
|
||||
CallableDescriptor functionDescriptor =
|
||||
(CallableDescriptor) trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, localDeclaration);
|
||||
JetType expectedType = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
|
||||
@@ -208,7 +212,7 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public void checkDefiniteReturn(final @NotNull JetType expectedReturnType) {
|
||||
public void checkDefiniteReturn(final @NotNull JetType expectedReturnType, @NotNull final UnreachableCode unreachableCode) {
|
||||
assert subroutine instanceof JetDeclarationWithBody;
|
||||
JetDeclarationWithBody function = (JetDeclarationWithBody) subroutine;
|
||||
|
||||
@@ -219,11 +223,6 @@ public class JetFlowInformationProvider {
|
||||
|
||||
final boolean blockBody = function.hasBlockBody();
|
||||
|
||||
final Set<JetElement> rootUnreachableElements = collectUnreachableCode();
|
||||
for (JetElement element : rootUnreachableElements) {
|
||||
trace.report(UNREACHABLE_CODE.on(element));
|
||||
}
|
||||
|
||||
final boolean[] noReturnError = new boolean[] { false };
|
||||
for (JetElement returnedExpression : returnedExpressions) {
|
||||
returnedExpression.accept(new JetVisitorVoid() {
|
||||
@@ -240,7 +239,7 @@ public class JetFlowInformationProvider {
|
||||
|
||||
if (blockBody && !noExpectedType(expectedReturnType)
|
||||
&& !KotlinBuiltIns.getInstance().isUnit(expectedReturnType)
|
||||
&& !rootUnreachableElements.contains(element)) {
|
||||
&& !unreachableCode.getElements().contains(element)) {
|
||||
noReturnError[0] = true;
|
||||
}
|
||||
}
|
||||
@@ -251,17 +250,25 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private Set<JetElement> collectUnreachableCode() {
|
||||
Collection<JetElement> unreachableElements = Lists.newArrayList();
|
||||
for (Instruction deadInstruction : pseudocode.getDeadInstructions()) {
|
||||
if (!(deadInstruction instanceof JetElementInstruction)
|
||||
|| deadInstruction instanceof LoadUnitValueInstruction
|
||||
|| deadInstruction instanceof MergeInstruction
|
||||
|| (deadInstruction instanceof MagicInstruction && ((MagicInstruction) deadInstruction).getSynthetic())) continue;
|
||||
private void reportUnreachableCode(@NotNull UnreachableCode unreachableCode) {
|
||||
for (JetElement element : unreachableCode.getElements()) {
|
||||
trace.report(UNREACHABLE_CODE.on(element, unreachableCode.getUnreachableTextRanges(element)));
|
||||
}
|
||||
}
|
||||
|
||||
JetElement element = ((JetElementInstruction) deadInstruction).getElement();
|
||||
@NotNull
|
||||
private UnreachableCode collectUnreachableCode() {
|
||||
Set<JetElement> reachableElements = Sets.newHashSet();
|
||||
Set<JetElement> unreachableElements = Sets.newHashSet();
|
||||
for (Instruction instruction : pseudocode.getInstructionsIncludingDeadCode()) {
|
||||
if (!(instruction instanceof JetElementInstruction)
|
||||
|| instruction instanceof LoadUnitValueInstruction
|
||||
|| instruction instanceof MergeInstruction
|
||||
|| (instruction instanceof MagicInstruction && ((MagicInstruction) instruction).getSynthetic())) continue;
|
||||
|
||||
if (deadInstruction instanceof JumpInstruction) {
|
||||
JetElement element = ((JetElementInstruction) instruction).getElement();
|
||||
|
||||
if (instruction instanceof JumpInstruction) {
|
||||
boolean isJumpElement = element instanceof JetBreakExpression
|
||||
|| element instanceof JetContinueExpression
|
||||
|| element instanceof JetReturnExpression
|
||||
@@ -269,10 +276,14 @@ public class JetFlowInformationProvider {
|
||||
if (!isJumpElement) continue;
|
||||
}
|
||||
|
||||
unreachableElements.add(element);
|
||||
if (instruction.getDead()) {
|
||||
unreachableElements.add(element);
|
||||
}
|
||||
else {
|
||||
reachableElements.add(element);
|
||||
}
|
||||
}
|
||||
// This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
|
||||
return JetPsiUtil.findRootExpressions(unreachableElements);
|
||||
return new UnreachableCodeImpl(reachableElements, unreachableElements);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -181,18 +181,10 @@ fun traverseFollowingInstructions(
|
||||
|
||||
while (!stack.isEmpty()) {
|
||||
val instruction = stack.pop()
|
||||
visited.add(instruction)
|
||||
if (!visited.add(instruction)) continue
|
||||
if (handler != null && !handler(instruction)) return false
|
||||
|
||||
val followingInstructions = instruction.getNextInstructions(order)
|
||||
|
||||
for (followingInstruction in followingInstructions) {
|
||||
if (!visited.contains(followingInstruction)) {
|
||||
if (handler != null && !handler(instruction)) {
|
||||
return false
|
||||
}
|
||||
stack.push(followingInstruction)
|
||||
}
|
||||
}
|
||||
instruction.getNextInstructions(order).forEach { stack.push(it) }
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.cfg
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetElement
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.jet.lexer.JetTokens
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.psi.PsiComment
|
||||
|
||||
trait UnreachableCode {
|
||||
val elements: Set<JetElement>
|
||||
fun getUnreachableTextRanges(element: JetElement): List<TextRange>
|
||||
}
|
||||
|
||||
class UnreachableCodeImpl(
|
||||
private val reachableElements: Set<JetElement>,
|
||||
private val unreachableElements: Set<JetElement>
|
||||
) : UnreachableCode {
|
||||
|
||||
// This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
|
||||
override val elements = JetPsiUtil.findRootExpressions(unreachableElements)
|
||||
|
||||
override fun getUnreachableTextRanges(element: JetElement): List<TextRange> {
|
||||
return if (element.hasChildrenInSet(reachableElements)) {
|
||||
element.getLeavesOrReachableChildren().removeReachableElementsWithMeaninglessSiblings().mergeAdjacentTextRanges()
|
||||
}
|
||||
else {
|
||||
listOf(element.getTextRange()!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun JetElement.hasChildrenInSet(set: Set<JetElement>): Boolean {
|
||||
return PsiTreeUtil.collectElements(this) { it != this }.any { it in set }
|
||||
}
|
||||
|
||||
private fun JetElement.getLeavesOrReachableChildren(): List<PsiElement> {
|
||||
val children = ArrayList<PsiElement>()
|
||||
acceptChildren(object : PsiElementVisitor() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
val isReachable = element is JetElement && reachableElements.contains(element) && !element.hasChildrenInSet(unreachableElements)
|
||||
if (isReachable || element.getChildren().size == 0) {
|
||||
children.add(element)
|
||||
}
|
||||
else {
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
}
|
||||
})
|
||||
return children
|
||||
}
|
||||
|
||||
fun List<PsiElement>.removeReachableElementsWithMeaninglessSiblings(): List<PsiElement> {
|
||||
fun PsiElement.isMeaningless() = this is PsiWhiteSpace
|
||||
|| this.getNode()?.getElementType() == JetTokens.COMMA
|
||||
|| this is PsiComment
|
||||
|
||||
val childrenToRemove = HashSet<PsiElement>()
|
||||
fun collectSiblingsIfMeaningless(elementIndex: Int, direction: Int) {
|
||||
val index = elementIndex + direction
|
||||
if (index !in 0..(size() - 1)) return
|
||||
|
||||
val element = this[index]
|
||||
if (element.isMeaningless()) {
|
||||
childrenToRemove.add(element)
|
||||
collectSiblingsIfMeaningless(index, direction)
|
||||
}
|
||||
}
|
||||
for ((index, element) in this.withIndices()) {
|
||||
if (reachableElements.contains(element)) {
|
||||
childrenToRemove.add(element)
|
||||
collectSiblingsIfMeaningless(index, -1)
|
||||
collectSiblingsIfMeaningless(index, 1)
|
||||
}
|
||||
}
|
||||
return this.filter { it !in childrenToRemove }
|
||||
}
|
||||
|
||||
|
||||
private fun List<PsiElement>.mergeAdjacentTextRanges(): List<TextRange> {
|
||||
val result = ArrayList<TextRange>()
|
||||
val lastRange = fold(null: TextRange?) {
|
||||
currentTextRange, element ->
|
||||
|
||||
val elementRange = element.getTextRange()!!
|
||||
if (currentTextRange == null) {
|
||||
elementRange
|
||||
}
|
||||
else if (currentTextRange.getEndOffset() == elementRange.getStartOffset()) {
|
||||
currentTextRange.union(elementRange)
|
||||
}
|
||||
else {
|
||||
result.add(currentTextRange)
|
||||
elementRange
|
||||
}
|
||||
}
|
||||
if (lastRange != null) {
|
||||
result.add(lastRange)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ public interface Pseudocode {
|
||||
List<Instruction> getReversedInstructions();
|
||||
|
||||
@NotNull
|
||||
List<Instruction> getDeadInstructions();
|
||||
List<Instruction> getInstructionsIncludingDeadCode();
|
||||
|
||||
@NotNull
|
||||
SubroutineExitInstruction getExitInstruction();
|
||||
|
||||
@@ -183,30 +183,10 @@ public class PseudocodeImpl implements Pseudocode {
|
||||
return Lists.newArrayList(traversedInstructions);
|
||||
}
|
||||
|
||||
//for tests only
|
||||
@NotNull
|
||||
public List<Instruction> getAllInstructions() {
|
||||
return mutableInstructionList;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<Instruction> getDeadInstructions() {
|
||||
List<Instruction> deadInstructions = Lists.newArrayList();
|
||||
for (Instruction instruction : mutableInstructionList) {
|
||||
if (isDead(instruction)) {
|
||||
deadInstructions.add(instruction);
|
||||
}
|
||||
}
|
||||
return deadInstructions;
|
||||
}
|
||||
|
||||
private static boolean isDead(@NotNull Instruction instruction) {
|
||||
if (!((InstructionImpl)instruction).getDead()) return false;
|
||||
for (Instruction copy : instruction.getCopies()) {
|
||||
if (!((InstructionImpl)copy).getDead()) return false;
|
||||
}
|
||||
return true;
|
||||
public List<Instruction> getInstructionsIncludingDeadCode() {
|
||||
return mutableInstructionList;
|
||||
}
|
||||
|
||||
//for tests only
|
||||
@@ -390,7 +370,7 @@ public class PseudocodeImpl implements Pseudocode {
|
||||
Set<Instruction> instructionSet = Sets.newHashSet(instructions);
|
||||
for (Instruction instruction : mutableInstructionList) {
|
||||
if (!instructionSet.contains(instruction)) {
|
||||
((InstructionImpl)instruction).die();
|
||||
((InstructionImpl)instruction).setMarkedAsDead(true);
|
||||
for (Instruction nextInstruction : instruction.getNextInstructions()) {
|
||||
nextInstruction.getPreviousInstructions().remove(instruction);
|
||||
}
|
||||
|
||||
@@ -28,16 +28,52 @@ public trait TypePredicate: (JetType) -> Boolean {
|
||||
}
|
||||
|
||||
public data class SingleType(val targetType: JetType): TypePredicate {
|
||||
override fun invoke(typeToCheck: JetType): Boolean = JetTypeChecker.INSTANCE.equalTypes(typeToCheck, targetType)
|
||||
override fun invoke(typeToCheck: JetType): Boolean = JetTypeChecker.DEFAULT.equalTypes(typeToCheck, targetType)
|
||||
override fun toString(): String = targetType.render()
|
||||
}
|
||||
|
||||
public data class AllSubtypes(val upperBound: JetType): TypePredicate {
|
||||
override fun invoke(typeToCheck: JetType): Boolean = JetTypeChecker.DEFAULT.isSubtypeOf(typeToCheck, upperBound)
|
||||
|
||||
override fun toString(): String = "{<: ${upperBound.render()}}"
|
||||
}
|
||||
|
||||
public data class ForAllTypes(val typeSets: List<TypePredicate>): TypePredicate {
|
||||
override fun invoke(typeToCheck: JetType): Boolean = typeSets.all { it(typeToCheck) }
|
||||
|
||||
override fun toString(): String = "AND{${typeSets.makeString(", ")}}"
|
||||
}
|
||||
|
||||
public data class ForSomeType(val typeSets: List<TypePredicate>): TypePredicate {
|
||||
override fun invoke(typeToCheck: JetType): Boolean = typeSets.any { it(typeToCheck) }
|
||||
|
||||
override fun toString(): String = "OR{${typeSets.makeString(", ")}}"
|
||||
}
|
||||
|
||||
public object AllTypes : TypePredicate {
|
||||
override fun invoke(typeToCheck: JetType): Boolean = true
|
||||
|
||||
override fun toString(): String = ""
|
||||
override fun toString(): String = "*"
|
||||
}
|
||||
|
||||
// todo: simplify computed type predicate when possible
|
||||
fun and(predicates: Collection<TypePredicate>): TypePredicate =
|
||||
when (predicates.size) {
|
||||
0 -> AllTypes
|
||||
1 -> predicates.first()
|
||||
else -> ForAllTypes(predicates.toList())
|
||||
}
|
||||
|
||||
fun or(predicates: Collection<TypePredicate>): TypePredicate? =
|
||||
when (predicates.size) {
|
||||
0 -> null
|
||||
1 -> predicates.first()
|
||||
else -> ForSomeType(predicates.toList())
|
||||
}
|
||||
|
||||
fun JetType.getSubtypesPredicate(): TypePredicate? =
|
||||
if (TypeUtils.canHaveSubtypes(JetTypeChecker.DEFAULT, this)) AllSubtypes(this) else SingleType(this)
|
||||
|
||||
private fun JetType.render(): String = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(this)
|
||||
|
||||
public fun <T> TypePredicate.expectedTypeFor(keys: Iterable<T>): Map<T, TypePredicate> =
|
||||
|
||||
+4
-2
@@ -23,14 +23,16 @@ import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue
|
||||
public trait Instruction {
|
||||
public var owner: Pseudocode
|
||||
|
||||
public val previousInstructions: MutableCollection<Instruction>
|
||||
public val previousInstructions: Collection<Instruction>
|
||||
public val nextInstructions: Collection<Instruction>
|
||||
|
||||
public val dead: Boolean
|
||||
|
||||
public val lexicalScope: LexicalScope
|
||||
|
||||
public val inputValues: List<PseudoValue>
|
||||
|
||||
public fun getCopies(): Collection<Instruction>
|
||||
public val copies: Collection<Instruction>
|
||||
|
||||
public fun accept(visitor: InstructionVisitor)
|
||||
public fun <R> accept(visitor: InstructionVisitorWithResult<R>): R
|
||||
|
||||
+27
-42
@@ -25,39 +25,6 @@ import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue
|
||||
|
||||
public abstract class InstructionImpl(public override val lexicalScope: LexicalScope): Instruction {
|
||||
private var _owner: Pseudocode? = null
|
||||
private val _copies = HashSet<Instruction>()
|
||||
private var original: Instruction? = null
|
||||
protected var _dead: Boolean = false
|
||||
|
||||
private fun setOriginalInstruction(value: Instruction?) {
|
||||
assert(original == null) { "Instruction can't have two originals: this.original = ${original}; new original = $this" }
|
||||
original = value
|
||||
}
|
||||
|
||||
protected fun outgoingEdgeTo(target: Instruction?): Instruction? {
|
||||
if (target != null) {
|
||||
target.previousInstructions.add(this)
|
||||
}
|
||||
return target
|
||||
}
|
||||
|
||||
protected fun updateCopyInfo(instruction: InstructionImpl): Instruction {
|
||||
_copies.add(instruction)
|
||||
instruction.setOriginalInstruction(this)
|
||||
return instruction
|
||||
}
|
||||
|
||||
protected abstract fun createCopy(): InstructionImpl
|
||||
|
||||
public fun die() {
|
||||
_dead = true
|
||||
}
|
||||
|
||||
public val dead: Boolean get() = _dead
|
||||
|
||||
public fun copy(): Instruction {
|
||||
return updateCopyInfo(createCopy())
|
||||
}
|
||||
|
||||
override var owner: Pseudocode
|
||||
get() = _owner!!
|
||||
@@ -66,16 +33,34 @@ public abstract class InstructionImpl(public override val lexicalScope: LexicalS
|
||||
_owner = value
|
||||
}
|
||||
|
||||
private var allCopies: MutableSet<InstructionImpl>? = null
|
||||
|
||||
override val copies: Collection<Instruction>
|
||||
get() = allCopies?.filter { it != this } ?: Collections.emptyList()
|
||||
|
||||
fun copy(): Instruction = updateCopyInfo(createCopy())
|
||||
|
||||
protected abstract fun createCopy(): InstructionImpl
|
||||
|
||||
protected fun updateCopyInfo(instruction: InstructionImpl): Instruction {
|
||||
if (allCopies == null) {
|
||||
allCopies = hashSetOf(this)
|
||||
}
|
||||
instruction.allCopies = allCopies
|
||||
allCopies!!.add(instruction)
|
||||
return instruction
|
||||
}
|
||||
|
||||
public var markedAsDead: Boolean = false
|
||||
|
||||
override val dead: Boolean get() = allCopies?.all { it.markedAsDead } ?: markedAsDead
|
||||
|
||||
override val previousInstructions: MutableCollection<Instruction> = LinkedHashSet()
|
||||
|
||||
override val inputValues: List<PseudoValue> = Collections.emptyList()
|
||||
|
||||
override fun getCopies(): Collection<Instruction> {
|
||||
return original?.let { original ->
|
||||
val originalCopies = Sets.newHashSet(original.getCopies())
|
||||
originalCopies.remove(this)
|
||||
originalCopies.add(original)
|
||||
originalCopies
|
||||
} ?: _copies
|
||||
protected fun outgoingEdgeTo(target: Instruction?): Instruction? {
|
||||
(target as InstructionImpl?)?.previousInstructions?.add(this)
|
||||
return target
|
||||
}
|
||||
|
||||
override val inputValues: List<PseudoValue> = Collections.emptyList()
|
||||
}
|
||||
@@ -16,13 +16,21 @@
|
||||
|
||||
package org.jetbrains.jet.lang.cfg.pseudocode
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetExpression
|
||||
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.traverseFollowingInstructions
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.TraversalOrder
|
||||
import org.jetbrains.jet.lang.psi.JetFunction
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteral
|
||||
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.*
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.*
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.*
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.*
|
||||
import org.jetbrains.jet.lang.psi.*
|
||||
import org.jetbrains.jet.lang.descriptors.*
|
||||
import org.jetbrains.jet.lang.resolve.bindingContextUtil.*
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.*
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import java.util.*
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.jet.lang.resolve.OverridingUtil
|
||||
import org.jetbrains.jet.lang.types.TypeUtils
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
|
||||
fun JetExpression.isStatement(pseudocode: Pseudocode): Boolean {
|
||||
val value = pseudocode.getElementValue(this);
|
||||
@@ -32,7 +40,7 @@ fun JetExpression.isStatement(pseudocode: Pseudocode): Boolean {
|
||||
return when {
|
||||
(getParent() as? JetFunction)?.getBodyExpression() == this ->
|
||||
true
|
||||
pseudocode.getElementValue(getParentByType(javaClass<JetFunctionLiteral>())?.getBodyExpression()) == value ->
|
||||
value.implicitReturnValue ->
|
||||
true
|
||||
else ->
|
||||
false
|
||||
@@ -42,4 +50,127 @@ fun JetExpression.isStatement(pseudocode: Pseudocode): Boolean {
|
||||
val instruction = value.createdAt
|
||||
if (considerUsedIfCreatedBeforeExit() && instruction.nextInstructions.any { it == pseudocode.getExitInstruction() }) return false
|
||||
return traverseFollowingInstructions(instruction, HashSet(), TraversalOrder.FORWARD) { value !in it.inputValues }
|
||||
}
|
||||
|
||||
val PseudoValue.implicitReturnValue: Boolean
|
||||
get() {
|
||||
val pseudocode = createdAt.owner
|
||||
|
||||
val function = pseudocode.getCorrespondingElement() as? JetDeclarationWithBody
|
||||
|
||||
if (function is JetFunctionLiteral || (function != null && !function.hasBlockBody())) {
|
||||
return pseudocode.getElementValue(function.getBodyExpression()) == this
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun Pseudocode.collectValueUsages(): Map<PseudoValue, List<Instruction>> {
|
||||
val map = HashMap<PseudoValue, MutableList<Instruction>>()
|
||||
traverseFollowingInstructions(getEnterInstruction(), HashSet(), TraversalOrder.FORWARD) {
|
||||
for (value in it.inputValues) {
|
||||
map.getOrPut(value){ ArrayList() }.add(it)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
|
||||
fun getReceiverTypePredicate(resolvedCall: ResolvedCall<*>, receiverValue: ReceiverValue): TypePredicate? {
|
||||
val callableDescriptor = resolvedCall.getResultingDescriptor()
|
||||
if (callableDescriptor == null) return null
|
||||
|
||||
when (receiverValue) {
|
||||
resolvedCall.getReceiverArgument() -> {
|
||||
val receiverParameter = callableDescriptor.getReceiverParameter()
|
||||
if (receiverParameter != null) return receiverParameter.getType().getSubtypesPredicate()
|
||||
}
|
||||
resolvedCall.getThisObject() -> {
|
||||
val rootCallableDescriptors = OverridingUtil.getTopmostOverridenDescriptors(callableDescriptor)
|
||||
return or(rootCallableDescriptors.map {
|
||||
it.getExpectedThisObject()?.getType()?.let { TypeUtils.makeNullableIfNeeded(it, resolvedCall.isSafeCall()) }?.getSubtypesPredicate()
|
||||
}.filterNotNull())
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun getExpectedTypePredicate(
|
||||
value: PseudoValue,
|
||||
valueUsageMap: Map<PseudoValue, List<Instruction>>,
|
||||
bindingContext: BindingContext
|
||||
): TypePredicate {
|
||||
val typePredicates = HashSet<TypePredicate?>()
|
||||
|
||||
fun addSubtypesOf(jetType: JetType?) = typePredicates.add(jetType?.getSubtypesPredicate())
|
||||
|
||||
fun addTypePredicates(value: PseudoValue) {
|
||||
if (value.implicitReturnValue) {
|
||||
val function = value.createdAt.owner.getCorrespondingElement() as? JetDeclarationWithBody
|
||||
val functionDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, function] as? FunctionDescriptor
|
||||
addSubtypesOf(functionDescriptor?.getReturnType())
|
||||
}
|
||||
|
||||
valueUsageMap[value]?.forEach {
|
||||
when (it) {
|
||||
is ReturnValueInstruction -> {
|
||||
val functionDescriptor = (it.element as JetReturnExpression).getTargetFunctionDescriptor(bindingContext)
|
||||
addSubtypesOf(functionDescriptor?.getReturnType())
|
||||
}
|
||||
|
||||
is ConditionalJumpInstruction ->
|
||||
addSubtypesOf(KotlinBuiltIns.getInstance().getBooleanType())
|
||||
|
||||
is ThrowExceptionInstruction ->
|
||||
addSubtypesOf(KotlinBuiltIns.getInstance().getThrowable().getDefaultType())
|
||||
|
||||
is MergeInstruction ->
|
||||
addTypePredicates(it.outputValue)
|
||||
|
||||
is AccessValueInstruction -> {
|
||||
val accessTarget = it.target
|
||||
val receiverValue = it.receiverValues[value]
|
||||
if (receiverValue != null) {
|
||||
typePredicates.add(getReceiverTypePredicate((accessTarget as AccessTarget.Call).resolvedCall, receiverValue))
|
||||
}
|
||||
else {
|
||||
val expectedType = when (accessTarget) {
|
||||
is AccessTarget.Call ->
|
||||
(accessTarget.resolvedCall.getResultingDescriptor() as? VariableDescriptor)?.getType()
|
||||
is AccessTarget.Declaration ->
|
||||
accessTarget.descriptor.getType()
|
||||
else ->
|
||||
null
|
||||
}
|
||||
addSubtypesOf(expectedType)
|
||||
}
|
||||
}
|
||||
|
||||
is CallInstruction -> {
|
||||
val receiverValue = it.receiverValues[value]
|
||||
if (receiverValue != null) {
|
||||
typePredicates.add(getReceiverTypePredicate(it.resolvedCall, receiverValue))
|
||||
}
|
||||
else {
|
||||
it.arguments[value]?.let { parameter ->
|
||||
val expectedType = when (it.resolvedCall.getValueArguments()[parameter]) {
|
||||
is VarargValueArgument ->
|
||||
parameter.getVarargElementType()
|
||||
else ->
|
||||
parameter.getType()
|
||||
}
|
||||
addSubtypesOf(expectedType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is MagicInstruction ->
|
||||
typePredicates.add(it.expectedTypes[value])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addTypePredicates(value)
|
||||
return and(typePredicates.filterNotNull())
|
||||
}
|
||||
@@ -27,6 +27,7 @@ public abstract class AbstractDiagnostic<E extends PsiElement> implements Parame
|
||||
private final E psiElement;
|
||||
private final DiagnosticFactoryWithPsiElement<E, ?> factory;
|
||||
private final Severity severity;
|
||||
private List<TextRange> textRanges;
|
||||
|
||||
public AbstractDiagnostic(@NotNull E psiElement,
|
||||
@NotNull DiagnosticFactoryWithPsiElement<E, ?> factory,
|
||||
@@ -63,6 +64,9 @@ public abstract class AbstractDiagnostic<E extends PsiElement> implements Parame
|
||||
@Override
|
||||
@NotNull
|
||||
public List<TextRange> getTextRanges() {
|
||||
if (textRanges != null) {
|
||||
return textRanges;
|
||||
}
|
||||
return getFactory().getTextRanges(this);
|
||||
}
|
||||
|
||||
@@ -71,4 +75,10 @@ public abstract class AbstractDiagnostic<E extends PsiElement> implements Parame
|
||||
if (!getFactory().isValid(this)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Diagnostic setTextRanges(@NotNull List<TextRange> textRanges) {
|
||||
this.textRanges = textRanges;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ public abstract class DiagnosticFactoryWithPsiElement<E extends PsiElement, D ex
|
||||
}
|
||||
|
||||
protected List<TextRange> getTextRanges(ParametrizedDiagnostic<E> diagnostic) {
|
||||
return positioningStrategy.mark(diagnostic.getPsiElement());
|
||||
return positioningStrategy.markDiagnostic(diagnostic);
|
||||
}
|
||||
|
||||
protected boolean isValid(ParametrizedDiagnostic<E> diagnostic) {
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
package org.jetbrains.jet.lang.diagnostics;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import kotlin.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -446,7 +448,13 @@ public interface Errors {
|
||||
|
||||
// Control flow / Data flow
|
||||
|
||||
DiagnosticFactory0<JetElement> UNREACHABLE_CODE = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory1<JetElement, List<TextRange>> UNREACHABLE_CODE = DiagnosticFactory1.create(
|
||||
WARNING, PositioningStrategies.markTextRangesFromDiagnostic(new Function1<Diagnostic, List<TextRange>>() {
|
||||
@Override
|
||||
public List<TextRange> invoke(Diagnostic diagnostic) {
|
||||
return UNREACHABLE_CODE.cast(diagnostic).getA();
|
||||
}
|
||||
}));
|
||||
|
||||
DiagnosticFactory0<JetVariableDeclaration> VARIABLE_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, NAME_IDENTIFIER);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
import kotlin.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -527,6 +528,18 @@ public class PositioningStrategies {
|
||||
}
|
||||
};
|
||||
|
||||
public static PositioningStrategy<PsiElement> markTextRangesFromDiagnostic(
|
||||
@NotNull final Function1<Diagnostic, List<TextRange>> getTextRanges
|
||||
) {
|
||||
return new PositioningStrategy<PsiElement>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<TextRange> markDiagnostic(@NotNull ParametrizedDiagnostic<? extends PsiElement> diagnostic) {
|
||||
return getTextRanges.invoke(diagnostic);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private PositioningStrategies() {
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,12 @@ import java.util.List;
|
||||
|
||||
public class PositioningStrategy<E extends PsiElement> {
|
||||
@NotNull
|
||||
public List<TextRange> mark(@NotNull E element) {
|
||||
public List<TextRange> markDiagnostic(@NotNull ParametrizedDiagnostic<? extends E> diagnostic) {
|
||||
return mark(diagnostic.getPsiElement());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected List<TextRange> mark(@NotNull E element) {
|
||||
return markElement(element);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -212,7 +212,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER,
|
||||
"Setter of this property can be overridden, so initialization using backing field required", NAME);
|
||||
|
||||
MAP.put(UNREACHABLE_CODE, "Unreachable code");
|
||||
MAP.put(UNREACHABLE_CODE, "Unreachable code", TO_STRING);
|
||||
|
||||
MAP.put(MANY_CLASS_OBJECTS, "Only one class object is allowed per class");
|
||||
MAP.put(CLASS_OBJECT_NOT_ALLOWED, "A class object is not allowed here");
|
||||
|
||||
@@ -229,13 +229,13 @@ public class Renderers {
|
||||
parameterTypes.add(valueParameterDescriptor.getType());
|
||||
if (valueParameterDescriptor.getIndex() >= inferenceErrorData.valueArgumentsTypes.size()) continue;
|
||||
JetType actualType = inferenceErrorData.valueArgumentsTypes.get(valueParameterDescriptor.getIndex());
|
||||
if (!JetTypeChecker.INSTANCE.isSubtypeOf(actualType, valueParameterDescriptor.getType())) {
|
||||
if (!JetTypeChecker.DEFAULT.isSubtypeOf(actualType, valueParameterDescriptor.getType())) {
|
||||
errorPositions.add(ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
|
||||
}
|
||||
}
|
||||
|
||||
if (receiverType != null && inferenceErrorData.receiverArgumentType != null &&
|
||||
!JetTypeChecker.INSTANCE.isSubtypeOf(inferenceErrorData.receiverArgumentType, receiverType)) {
|
||||
!JetTypeChecker.DEFAULT.isSubtypeOf(inferenceErrorData.receiverArgumentType, receiverType)) {
|
||||
errorPositions.add(ConstraintPosition.RECEIVER_POSITION);
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ public class Renderers {
|
||||
JetType upperBoundWithSubstitutedInferredTypes =
|
||||
systemWithoutWeakConstraints.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT);
|
||||
if (upperBoundWithSubstitutedInferredTypes != null &&
|
||||
!JetTypeChecker.INSTANCE.isSubtypeOf(inferredValueForTypeParameter, upperBoundWithSubstitutedInferredTypes)) {
|
||||
!JetTypeChecker.DEFAULT.isSubtypeOf(inferredValueForTypeParameter, upperBoundWithSubstitutedInferredTypes)) {
|
||||
violatedUpperBound = upperBoundWithSubstitutedInferredTypes;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -780,13 +780,13 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
|
||||
// Parse when block
|
||||
myBuilder.enableNewlines();
|
||||
expect(LBRACE, "Expecting '{'");
|
||||
if (expect(LBRACE, "Expecting '{'")) {
|
||||
while (!eof() && !at(RBRACE)) {
|
||||
parseWhenEntry();
|
||||
}
|
||||
|
||||
while (!eof() && !at(RBRACE)) {
|
||||
parseWhenEntry();
|
||||
expect(RBRACE, "Expecting '}'");
|
||||
}
|
||||
|
||||
expect(RBRACE, "Expecting '}'");
|
||||
myBuilder.restoreNewlinesState();
|
||||
|
||||
when.done(WHEN);
|
||||
@@ -1370,35 +1370,40 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
|
||||
advance(); // FOR_KEYWORD
|
||||
|
||||
myBuilder.disableNewlines();
|
||||
expect(LPAR, "Expecting '(' to open a loop range", TokenSet.create(RPAR, VAL_KEYWORD, VAR_KEYWORD, IDENTIFIER));
|
||||
if (expect(LPAR, "Expecting '(' to open a loop range", EXPRESSION_FIRST)) {
|
||||
myBuilder.disableNewlines();
|
||||
|
||||
PsiBuilder.Marker parameter = mark();
|
||||
if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD
|
||||
if (at(LPAR)) {
|
||||
myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE));
|
||||
if (!at(RPAR)) {
|
||||
PsiBuilder.Marker parameter = mark();
|
||||
if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD
|
||||
if (at(LPAR)) {
|
||||
myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE));
|
||||
parameter.done(MULTI_VARIABLE_DECLARATION);
|
||||
}
|
||||
else {
|
||||
expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON, IN_KEYWORD));
|
||||
|
||||
parameter.done(MULTI_VARIABLE_DECLARATION);
|
||||
}
|
||||
else {
|
||||
expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON));
|
||||
if (at(COLON)) {
|
||||
advance(); // COLON
|
||||
myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD));
|
||||
}
|
||||
parameter.done(VALUE_PARAMETER);
|
||||
}
|
||||
|
||||
if (at(COLON)) {
|
||||
advance(); // COLON
|
||||
myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD));
|
||||
if (expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE, RPAR))) {
|
||||
PsiBuilder.Marker range = mark();
|
||||
parseExpression();
|
||||
range.done(LOOP_RANGE);
|
||||
}
|
||||
}
|
||||
parameter.done(VALUE_PARAMETER);
|
||||
else {
|
||||
error("Expecting a variable name");
|
||||
}
|
||||
|
||||
expectNoAdvance(RPAR, "Expecting ')'");
|
||||
myBuilder.restoreNewlinesState();
|
||||
}
|
||||
|
||||
expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE));
|
||||
|
||||
PsiBuilder.Marker range = mark();
|
||||
parseExpression();
|
||||
range.done(LOOP_RANGE);
|
||||
|
||||
expectNoAdvance(RPAR, "Expecting ')'");
|
||||
myBuilder.restoreNewlinesState();
|
||||
|
||||
parseControlStructureBody();
|
||||
|
||||
loop.done(FOR);
|
||||
@@ -1548,13 +1553,14 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
*/
|
||||
private void parseCondition() {
|
||||
myBuilder.disableNewlines();
|
||||
expect(LPAR, "Expecting a condition in parentheses '(...)'");
|
||||
|
||||
PsiBuilder.Marker condition = mark();
|
||||
parseExpression();
|
||||
condition.done(CONDITION);
|
||||
if (expect(LPAR, "Expecting a condition in parentheses '(...)'", EXPRESSION_FIRST)) {
|
||||
PsiBuilder.Marker condition = mark();
|
||||
parseExpression();
|
||||
condition.done(CONDITION);
|
||||
expect(RPAR, "Expecting ')");
|
||||
}
|
||||
|
||||
expect(RPAR, "Expecting ')");
|
||||
myBuilder.restoreNewlinesState();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,10 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
public class JetDoWhileExpression extends JetWhileExpressionBase {
|
||||
public JetDoWhileExpression(@NotNull ASTNode node) {
|
||||
@@ -28,4 +31,11 @@ public class JetDoWhileExpression extends JetWhileExpressionBase {
|
||||
public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitDoWhileExpression(this, data);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@IfNotParsed
|
||||
public PsiElement getWhileKeywordElement() {
|
||||
//noinspection ConstantConditions
|
||||
return findChildByType(JetTokens.WHILE_KEYWORD);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +17,11 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
public class JetIfExpression extends JetExpressionImpl {
|
||||
public JetIfExpression(@NotNull ASTNode node) {
|
||||
@@ -36,6 +38,16 @@ public class JetIfExpression extends JetExpressionImpl {
|
||||
return findExpressionUnder(JetNodeTypes.CONDITION);
|
||||
}
|
||||
|
||||
@Nullable @IfNotParsed
|
||||
public PsiElement getLeftParenthesis() {
|
||||
return findChildByType(JetTokens.LPAR);
|
||||
}
|
||||
|
||||
@Nullable @IfNotParsed
|
||||
public PsiElement getRightParenthesis() {
|
||||
return findChildByType(JetTokens.RPAR);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetExpression getThen() {
|
||||
return findExpressionUnder(JetNodeTypes.THEN);
|
||||
@@ -45,4 +57,9 @@ public class JetIfExpression extends JetExpressionImpl {
|
||||
public JetExpression getElse() {
|
||||
return findExpressionUnder(JetNodeTypes.ELSE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getElseKeyword() {
|
||||
return findChildByType(JetTokens.ELSE_KEYWORD);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +17,11 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
public abstract class JetLoopExpression extends JetExpressionImpl implements JetStatementExpression {
|
||||
public JetLoopExpression(@NotNull ASTNode node) {
|
||||
@@ -30,4 +32,15 @@ public abstract class JetLoopExpression extends JetExpressionImpl implements Jet
|
||||
public JetExpression getBody() {
|
||||
return findExpressionUnder(JetNodeTypes.BODY);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@IfNotParsed
|
||||
public PsiElement getLeftParenthesis() {
|
||||
return findChildByType(JetTokens.LPAR);
|
||||
}
|
||||
|
||||
@Nullable @IfNotParsed
|
||||
public PsiElement getRightParenthesis() {
|
||||
return findChildByType(JetTokens.RPAR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,13 +47,28 @@ public class JetWhenExpression extends JetExpressionImpl {
|
||||
|
||||
@NotNull
|
||||
public PsiElement getWhenKeywordElement() {
|
||||
//noinspection ConstantConditions
|
||||
return findChildByType(JetTokens.WHEN_KEYWORD);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getCloseBraceNode() {
|
||||
ASTNode openBraceNode = getNode().findChildByType(JetTokens.RBRACE);
|
||||
return openBraceNode != null ? openBraceNode.getPsi() : null;
|
||||
public PsiElement getCloseBrace() {
|
||||
return findChildByType(JetTokens.RBRACE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getOpenBrace() {
|
||||
return findChildByType(JetTokens.LBRACE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getLeftParenthesis() {
|
||||
return findChildByType(JetTokens.LPAR);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getRightParenthesis() {
|
||||
return findChildByType(JetTokens.RPAR);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ import org.jetbrains.jet.plugin.JetLanguage;
|
||||
import java.io.IOException;
|
||||
|
||||
public class JetFileElementType extends IStubFileElementType<PsiJetFileStub> {
|
||||
public static final int STUB_VERSION = 28;
|
||||
public static final int STUB_VERSION = 29;
|
||||
|
||||
public JetFileElementType() {
|
||||
super("jet.FILE", JetLanguage.INSTANCE);
|
||||
|
||||
+10
-48
@@ -23,13 +23,14 @@ import com.intellij.psi.stubs.IndexSink;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.IStubFileElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayFactory;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetElementImplStub;
|
||||
import org.jetbrains.jet.lang.psi.JetFunction;
|
||||
import org.jetbrains.jet.lang.psi.JetProperty;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
@@ -37,9 +38,6 @@ import java.lang.reflect.Constructor;
|
||||
|
||||
public abstract class JetStubElementType<StubT extends StubElement, PsiT extends JetElementImplStub<?>> extends IStubElementType<StubT, PsiT> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final Class<? extends PsiElement>[] ALWAYS_CREATE_STUB_FOR = new Class[] { JetClass.class, JetObjectDeclaration.class };
|
||||
|
||||
@NotNull
|
||||
private final Constructor<PsiT> byNodeConstructor;
|
||||
@NotNull
|
||||
@@ -93,11 +91,14 @@ public abstract class JetStubElementType<StubT extends StubElement, PsiT extends
|
||||
@Override
|
||||
public boolean shouldCreateStub(ASTNode node) {
|
||||
PsiElement psi = node.getPsi();
|
||||
if (ArrayUtil.contains(psi.getClass(), (Object[]) ALWAYS_CREATE_STUB_FOR)) {
|
||||
if (psi instanceof JetClassOrObject) {
|
||||
return true;
|
||||
}
|
||||
if (psi instanceof JetDeclaration) {
|
||||
return shouldCreateStubForDeclaration((JetDeclaration) psi);
|
||||
if (psi instanceof JetFunction) {
|
||||
return !((JetFunction) psi).isLocal();
|
||||
}
|
||||
if (psi instanceof JetProperty) {
|
||||
return !((JetProperty) psi).isLocal();
|
||||
}
|
||||
return createStubDependingOnParent(node);
|
||||
}
|
||||
@@ -114,45 +115,6 @@ public abstract class JetStubElementType<StubT extends StubElement, PsiT extends
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean shouldCreateStubForDeclaration(@NotNull JetDeclaration declaration) {
|
||||
// Do not create stubs inside function literals
|
||||
//noinspection unchecked
|
||||
if (PsiTreeUtil.getParentOfType(declaration, JetFunctionLiteral.class, false, ALWAYS_CREATE_STUB_FOR) != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't create stubs if declaration is inside function or property accessor with block
|
||||
//noinspection unchecked
|
||||
JetBlockExpression blockExpression =
|
||||
PsiTreeUtil.getParentOfType(declaration, JetBlockExpression.class, false, ALWAYS_CREATE_STUB_FOR);
|
||||
if (blockExpression != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't create stubs if declaration is inside other declaration with expression initializer
|
||||
|
||||
Class<? extends PsiElement>[] stopAt = ArrayUtil.append(ALWAYS_CREATE_STUB_FOR, JetBlockExpression.class);
|
||||
@SuppressWarnings("unchecked") JetWithExpressionInitializer withInitializer =
|
||||
PsiTreeUtil.getParentOfType(declaration, JetWithExpressionInitializer.class, true, stopAt);
|
||||
if (withInitializer != null) {
|
||||
JetExpression initializer = withInitializer.getInitializer();
|
||||
if (PsiTreeUtil.isAncestor(initializer, declaration, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't create stubs if declaration is inside property delegate
|
||||
@SuppressWarnings("unchecked") JetPropertyDelegate delegate = PsiTreeUtil.getParentOfType(declaration, JetPropertyDelegate.class, true, stopAt);
|
||||
if (delegate != null) {
|
||||
JetExpression delegateExpression = delegate.getExpression();
|
||||
if (PsiTreeUtil.isAncestor(delegateExpression, declaration, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void indexStub(@NotNull StubT stub, @NotNull IndexSink sink) {
|
||||
// do not force inheritors to implement this method
|
||||
|
||||
@@ -21,14 +21,18 @@ import org.jetbrains.jet.lang.psi.Call
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil
|
||||
import org.jetbrains.jet.lang.psi.JetCallExpression
|
||||
import org.jetbrains.jet.lang.psi.JetQualifiedExpression
|
||||
import org.jetbrains.jet.lang.psi.JetBinaryExpression
|
||||
import org.jetbrains.jet.lang.psi.JetUnaryExpression
|
||||
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.psi.JetOperationExpression
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext.CALL
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.jet.lang.psi.JetReturnExpression
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext.LABEL_TARGET
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext.FUNCTION
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
|
||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils
|
||||
import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor
|
||||
|
||||
/**
|
||||
* For expressions like <code>a(), a[i], a.b.c(), +a, a + b, (a()), a(): Int, @label a()</code>
|
||||
@@ -51,3 +55,16 @@ fun JetExpression.getCorrespondingCall(bindingContext: BindingContext): Call? {
|
||||
}
|
||||
return bindingContext[CALL, reference]
|
||||
}
|
||||
|
||||
public fun JetReturnExpression.getTargetFunctionDescriptor(bindingContext: BindingContext): FunctionDescriptor? {
|
||||
val targetLabel = getTargetLabel()
|
||||
if (targetLabel != null) return bindingContext[LABEL_TARGET, targetLabel]?.let { bindingContext[FUNCTION, it] }
|
||||
|
||||
val declarationDescriptor = bindingContext[DECLARATION_TO_DESCRIPTOR, getParentByType(javaClass<JetDeclarationWithBody>())]
|
||||
val containingFunctionDescriptor = DescriptorUtils.getParentOfType(declarationDescriptor, javaClass<FunctionDescriptor>(), false)
|
||||
if (containingFunctionDescriptor == null) return null
|
||||
|
||||
return stream(containingFunctionDescriptor) { DescriptorUtils.getParentOfType(it, javaClass<FunctionDescriptor>()) }
|
||||
.dropWhile { it is AnonymousFunctionDescriptor }
|
||||
.firstOrNull()
|
||||
}
|
||||
|
||||
@@ -220,13 +220,13 @@ public class DeclarationsChecker {
|
||||
REMOVE_IF_SUBTYPE_IN_THE_SET {
|
||||
@Override
|
||||
public boolean removeNeeded(JetType subject, JetType other) {
|
||||
return JetTypeChecker.INSTANCE.isSubtypeOf(other, subject);
|
||||
return JetTypeChecker.DEFAULT.isSubtypeOf(other, subject);
|
||||
}
|
||||
},
|
||||
REMOVE_IF_SUPERTYPE_IN_THE_SET {
|
||||
@Override
|
||||
public boolean removeNeeded(JetType subject, JetType other) {
|
||||
return JetTypeChecker.INSTANCE.isSubtypeOf(subject, other);
|
||||
return JetTypeChecker.DEFAULT.isSubtypeOf(subject, other);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ public class DelegatedPropertyResolver {
|
||||
JetType propertyType = propertyDescriptor.getType();
|
||||
|
||||
/* Do not check return type of get() method of delegate for properties with DeferredType because property type is taken from it */
|
||||
if (!(propertyType instanceof DeferredType) && returnType != null && !JetTypeChecker.INSTANCE.isSubtypeOf(returnType, propertyType)) {
|
||||
if (!(propertyType instanceof DeferredType) && returnType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(returnType, propertyType)) {
|
||||
Call call = trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, propertyDescriptor.getGetter());
|
||||
assert call != null : "Call should exists for " + propertyDescriptor.getGetter();
|
||||
trace.report(DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH
|
||||
|
||||
@@ -760,7 +760,7 @@ public class DescriptorResolver {
|
||||
boolean isClassObjectConstraint,
|
||||
BindingTrace trace
|
||||
) {
|
||||
if (!TypeUtils.canHaveSubtypes(JetTypeChecker.INSTANCE, upperBoundType)) {
|
||||
if (!TypeUtils.canHaveSubtypes(JetTypeChecker.DEFAULT, upperBoundType)) {
|
||||
if (isClassObjectConstraint) {
|
||||
trace.report(FINAL_CLASS_OBJECT_UPPER_BOUND.on(upperBound, upperBoundType));
|
||||
}
|
||||
@@ -1360,7 +1360,7 @@ public class DescriptorResolver {
|
||||
) {
|
||||
for (JetType bound : typeParameterDescriptor.getUpperBounds()) {
|
||||
JetType substitutedBound = substitutor.safeSubstitute(bound, Variance.INVARIANT);
|
||||
if (!JetTypeChecker.INSTANCE.isSubtypeOf(typeArgument, substitutedBound)) {
|
||||
if (!JetTypeChecker.DEFAULT.isSubtypeOf(typeArgument, substitutedBound)) {
|
||||
trace.report(UPPER_BOUND_VIOLATED.on(jetTypeArgument, substitutedBound, typeArgument));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public class OverloadUtil {
|
||||
JetType superValueParameterType = OverridingUtil.getUpperBound(superValueParameters.get(i));
|
||||
JetType subValueParameterType = OverridingUtil.getUpperBound(subValueParameters.get(i));
|
||||
// TODO: compare erasure
|
||||
if (!JetTypeChecker.INSTANCE.equalTypes(superValueParameterType, subValueParameterType)) {
|
||||
if (!JetTypeChecker.DEFAULT.equalTypes(superValueParameterType, subValueParameterType)) {
|
||||
return OverridingUtil.OverrideCompatibilityInfo
|
||||
.valueParameterTypeMismatch(superValueParameterType, subValueParameterType, INCOMPATIBLE);
|
||||
}
|
||||
|
||||
@@ -733,7 +733,7 @@ public class OverrideResolver {
|
||||
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE);
|
||||
assert substitutedSuperReturnType != null;
|
||||
|
||||
return JetTypeChecker.INSTANCE.isSubtypeOf(subReturnType, substitutedSuperReturnType);
|
||||
return JetTypeChecker.DEFAULT.isSubtypeOf(subReturnType, substitutedSuperReturnType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -768,7 +768,7 @@ public class OverrideResolver {
|
||||
|
||||
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getType(), Variance.OUT_VARIANCE);
|
||||
assert substitutedSuperReturnType != null;
|
||||
return JetTypeChecker.INSTANCE.equalTypes(subDescriptor.getType(), substitutedSuperReturnType);
|
||||
return JetTypeChecker.DEFAULT.equalTypes(subDescriptor.getType(), substitutedSuperReturnType);
|
||||
}
|
||||
|
||||
private void checkOverrideForComponentFunction(@NotNull final CallableMemberDescriptor componentFunction) {
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ public class ArgumentTypeResolver {
|
||||
if (actualType == PLACEHOLDER_FUNCTION_TYPE) {
|
||||
return isFunctionOrErrorType(expectedType) || KotlinBuiltIns.getInstance().isAnyOrNullableAny(expectedType); //todo function type extends
|
||||
}
|
||||
return JetTypeChecker.INSTANCE.isSubtypeOf(actualType, expectedType);
|
||||
return JetTypeChecker.DEFAULT.isSubtypeOf(actualType, expectedType);
|
||||
}
|
||||
|
||||
private static boolean isFunctionOrErrorType(@NotNull JetType supertype) {
|
||||
|
||||
@@ -102,18 +102,22 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
|
||||
assert candidate.getDescriptor() instanceof VariableDescriptor;
|
||||
|
||||
boolean hasReceiver = candidate.getReceiverArgument().exists();
|
||||
Call variableCall = stripCallArguments(task);
|
||||
Call variableCall = stripCallArguments(task.call);
|
||||
ResolutionCandidate<CallableDescriptor> variableCandidate = getVariableCallCandidate(candidate, variableCall);
|
||||
if (!hasReceiver) {
|
||||
CallCandidateResolutionContext<CallableDescriptor> context = CallCandidateResolutionContext.create(
|
||||
ResolvedCallImpl.create(candidate, candidateTrace, task.tracing, task.dataFlowInfoForArguments), task, candidateTrace, task.tracing, variableCall);
|
||||
ResolvedCallImpl.create(variableCandidate, candidateTrace, task.tracing, task.dataFlowInfoForArguments), task, candidateTrace, task.tracing, variableCall);
|
||||
return Collections.singleton(context);
|
||||
}
|
||||
CallCandidateResolutionContext<CallableDescriptor> contextWithReceiver = createContextWithChainedTrace(
|
||||
candidate, variableCall, candidateTrace, task, ReceiverValue.NO_RECEIVER);
|
||||
variableCandidate, variableCall, candidateTrace, task, ReceiverValue.NO_RECEIVER);
|
||||
|
||||
Call variableCallWithoutReceiver = stripReceiver(variableCall);
|
||||
ResolutionCandidate<CallableDescriptor> candidateWithoutReceiver = ResolutionCandidate.create(
|
||||
candidate.getCall(), candidate.getDescriptor(), candidate.getThisObject(), ReceiverValue.NO_RECEIVER,
|
||||
variableCandidate.getCall(),
|
||||
variableCandidate.getDescriptor(),
|
||||
variableCandidate.getThisObject(),
|
||||
ReceiverValue.NO_RECEIVER,
|
||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, false);
|
||||
|
||||
CallCandidateResolutionContext<CallableDescriptor> contextWithoutReceiver = createContextWithChainedTrace(
|
||||
@@ -131,8 +135,22 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
|
||||
return CallCandidateResolutionContext.create(resolvedCall, task, chainedTrace, task.tracing, call, receiverValue);
|
||||
}
|
||||
|
||||
private Call stripCallArguments(@NotNull ResolutionTask<CallableDescriptor, FunctionDescriptor> task) {
|
||||
return new DelegatingCall(task.call) {
|
||||
@NotNull
|
||||
private ResolutionCandidate<CallableDescriptor> getVariableCallCandidate(
|
||||
@NotNull ResolutionCandidate<CallableDescriptor> candidate,
|
||||
@NotNull Call variableCall
|
||||
) {
|
||||
return ResolutionCandidate.create(
|
||||
variableCall,
|
||||
candidate.getDescriptor(),
|
||||
candidate.getThisObject(),
|
||||
candidate.getReceiverArgument(),
|
||||
candidate.getExplicitReceiverKind(),
|
||||
candidate.isSafeCall());
|
||||
}
|
||||
|
||||
private Call stripCallArguments(@NotNull Call call) {
|
||||
return new DelegatingCall(call) {
|
||||
@Override
|
||||
public JetValueArgumentList getValueArgumentList() {
|
||||
return null;
|
||||
@@ -160,6 +178,15 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
|
||||
public JetTypeArgumentList getTypeArgumentList() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetElement getCallElement() {
|
||||
JetExpression calleeExpression = getCalleeExpression();
|
||||
assert calleeExpression != null : "No callee expression: " + getCallElement().getText();
|
||||
|
||||
return calleeExpression;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -735,7 +735,7 @@ public class CandidateResolver {
|
||||
Set<JetType> possibleTypes = dataFlowInfoForArgument.getPossibleTypes(dataFlowValue);
|
||||
if (possibleTypes.isEmpty()) return type;
|
||||
|
||||
return TypeUtils.intersect(JetTypeChecker.INSTANCE, possibleTypes);
|
||||
return TypeUtils.intersect(JetTypeChecker.DEFAULT, possibleTypes);
|
||||
}
|
||||
|
||||
private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
|
||||
@@ -859,7 +859,7 @@ public class CandidateResolver {
|
||||
List<JetType> variants =
|
||||
AutoCastUtils.getAutoCastVariantsExcludingReceiver(context.trace.getBindingContext(), context.dataFlowInfo, receiverToCast);
|
||||
for (JetType possibleType : variants) {
|
||||
if (JetTypeChecker.INSTANCE.isSubtypeOf(possibleType, expectedType)) {
|
||||
if (JetTypeChecker.DEFAULT.isSubtypeOf(possibleType, expectedType)) {
|
||||
return possibleType;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -25,7 +25,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.Call;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetSuperExpression;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastUtils;
|
||||
@@ -326,7 +325,7 @@ public class TaskPrioritizer {
|
||||
if (expectedThisObject == null) return true;
|
||||
List<ReceiverParameterDescriptor> receivers = scope.getImplicitReceiversHierarchy();
|
||||
for (ReceiverParameterDescriptor receiver : receivers) {
|
||||
if (JetTypeChecker.INSTANCE.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) {
|
||||
if (JetTypeChecker.DEFAULT.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) {
|
||||
// TODO : Autocasts & nullability
|
||||
candidate.setThisObject(expectedThisObject.getValue());
|
||||
return true;
|
||||
|
||||
+4
-4
@@ -90,7 +90,7 @@ public class CompileTimeConstantChecker {
|
||||
|
||||
if (!noExpectedTypeOrError(expectedType)) {
|
||||
JetType valueType = value.getType(KotlinBuiltIns.getInstance());
|
||||
if (!JetTypeChecker.INSTANCE.isSubtypeOf(valueType, expectedType)) {
|
||||
if (!JetTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) {
|
||||
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "integer", expectedType));
|
||||
}
|
||||
}
|
||||
@@ -107,7 +107,7 @@ public class CompileTimeConstantChecker {
|
||||
}
|
||||
if (!noExpectedTypeOrError(expectedType)) {
|
||||
JetType valueType = value.getType(KotlinBuiltIns.getInstance());
|
||||
if (!JetTypeChecker.INSTANCE.isSubtypeOf(valueType, expectedType)) {
|
||||
if (!JetTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) {
|
||||
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "floating-point", expectedType));
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ public class CompileTimeConstantChecker {
|
||||
@NotNull JetConstantExpression expression
|
||||
) {
|
||||
if (!noExpectedTypeOrError(expectedType)
|
||||
&& !JetTypeChecker.INSTANCE.isSubtypeOf(builtIns.getBooleanType(), expectedType)) {
|
||||
&& !JetTypeChecker.DEFAULT.isSubtypeOf(builtIns.getBooleanType(), expectedType)) {
|
||||
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "boolean", expectedType));
|
||||
}
|
||||
return false;
|
||||
@@ -127,7 +127,7 @@ public class CompileTimeConstantChecker {
|
||||
|
||||
private boolean checkCharValue(CompileTimeConstant<?> constant, JetType expectedType, JetConstantExpression expression) {
|
||||
if (!noExpectedTypeOrError(expectedType)
|
||||
&& !JetTypeChecker.INSTANCE.isSubtypeOf(builtIns.getCharType(), expectedType)) {
|
||||
&& !JetTypeChecker.DEFAULT.isSubtypeOf(builtIns.getCharType(), expectedType)) {
|
||||
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "character", expectedType));
|
||||
}
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@ public class CastDiagnosticsUtil {
|
||||
|
||||
for (JetType aType : aTypes) {
|
||||
for (JetType bType : bTypes) {
|
||||
if (JetTypeChecker.INSTANCE.isSubtypeOf(aType, bType)) return true;
|
||||
if (JetTypeChecker.INSTANCE.isSubtypeOf(bType, aType)) return true;
|
||||
if (JetTypeChecker.DEFAULT.isSubtypeOf(aType, bType)) return true;
|
||||
if (JetTypeChecker.DEFAULT.isSubtypeOf(bType, aType)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ public class CastDiagnosticsUtil {
|
||||
}
|
||||
|
||||
private static boolean isFinal(@NotNull JetType type) {
|
||||
return !TypeUtils.canHaveSubtypes(JetTypeChecker.INSTANCE, type);
|
||||
return !TypeUtils.canHaveSubtypes(JetTypeChecker.DEFAULT, type);
|
||||
}
|
||||
|
||||
private static boolean isTrait(@NotNull JetType type) {
|
||||
|
||||
+8
-7
@@ -212,7 +212,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
context.trace.report(CAST_NEVER_SUCCEEDS.on(expression.getOperationReference()));
|
||||
}
|
||||
else {
|
||||
JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
|
||||
JetTypeChecker typeChecker = JetTypeChecker.DEFAULT;
|
||||
// Upcast?
|
||||
if (typeChecker.isSubtypeOf(actualType, targetType)) {
|
||||
if (!typeChecker.isSubtypeOf(targetType, actualType)) {
|
||||
@@ -378,8 +378,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (labelName != null) {
|
||||
LabelResolver.LabeledReceiverResolutionResult resolutionResult =
|
||||
LabelResolver.INSTANCE.resolveThisOrSuperLabel(expression, context, Name.identifier(labelName));
|
||||
if (onlyClassReceivers && resolutionResult.success()) {
|
||||
if (!isDeclaredInClass(resolutionResult.getReceiverParameterDescriptor())) {
|
||||
if (resolutionResult.success()) {
|
||||
ReceiverParameterDescriptor receiverParameterDescriptor = resolutionResult.getReceiverParameterDescriptor();
|
||||
recordThisOrSuperCallInTraceAndCallExtension(context, receiverParameterDescriptor, expression);
|
||||
if (onlyClassReceivers && !isDeclaredInClass(receiverParameterDescriptor)) {
|
||||
return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(NO_RECEIVER_PARAMETER);
|
||||
}
|
||||
}
|
||||
@@ -402,7 +404,6 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (result != NO_RECEIVER_PARAMETER) {
|
||||
context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), result.getContainingDeclaration());
|
||||
recordThisOrSuperCallInTraceAndCallExtension(context, result, expression);
|
||||
|
||||
}
|
||||
return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(result);
|
||||
}
|
||||
@@ -661,13 +662,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetType result;
|
||||
if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
|
||||
assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor();
|
||||
if (JetTypeChecker.INSTANCE.isSubtypeOf(returnType, KotlinBuiltIns.getInstance().getUnitType())) {
|
||||
if (KotlinBuiltIns.getInstance().isUnit(returnType)) {
|
||||
result = ErrorUtils.createErrorType(KotlinBuiltIns.getInstance().getUnit().getName().asString());
|
||||
context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign));
|
||||
}
|
||||
else {
|
||||
JetType receiverType = receiver.getType();
|
||||
if (!JetTypeChecker.INSTANCE.isSubtypeOf(returnType, receiverType)) {
|
||||
if (!JetTypeChecker.DEFAULT.isSubtypeOf(returnType, receiverType)) {
|
||||
context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType));
|
||||
}
|
||||
else {
|
||||
@@ -882,7 +883,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:", right);
|
||||
traceInterpretingRightAsNullableAny.record(EXPRESSION_TYPE, right, KotlinBuiltIns.getInstance().getNullableAnyType());
|
||||
|
||||
Call call = CallMaker.makeCallWithExpressions(operationSign, receiver, null, operationSign, Collections.singletonList(right));
|
||||
Call call = CallMaker.makeCallWithExpressions(expression, receiver, null, operationSign, Collections.singletonList(right));
|
||||
ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny);
|
||||
OverloadResolutionResults<FunctionDescriptor> resolutionResults =
|
||||
components.callResolver.resolveCallWithGivenName(newContext, call, operationSign, OperatorConventions.EQUALS);
|
||||
|
||||
+2
-2
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -355,7 +355,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
variableDescriptor = components.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(context.scope, loopParameter, context.trace);
|
||||
JetType actualParameterType = variableDescriptor.getType();
|
||||
if (expectedParameterType != null &&
|
||||
!JetTypeChecker.INSTANCE.isSubtypeOf(expectedParameterType, actualParameterType)) {
|
||||
!JetTypeChecker.DEFAULT.isSubtypeOf(expectedParameterType, actualParameterType)) {
|
||||
context.trace.report(TYPE_MISMATCH_IN_FOR_LOOP.on(typeReference, expectedParameterType, actualParameterType));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ public class DataFlowUtils {
|
||||
recordExpectedType(trace, expression, expectedType);
|
||||
|
||||
if (expressionType == null || noExpectedType(expectedType) || !expectedType.getConstructor().isDenotable() ||
|
||||
JetTypeChecker.INSTANCE.isSubtypeOf(expressionType, expectedType)) {
|
||||
JetTypeChecker.DEFAULT.isSubtypeOf(expressionType, expectedType)) {
|
||||
return expressionType;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ public class DataFlowUtils {
|
||||
|
||||
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, expressionType, trace.getBindingContext());
|
||||
for (JetType possibleType : dataFlowInfo.getPossibleTypes(dataFlowValue)) {
|
||||
if (JetTypeChecker.INSTANCE.isSubtypeOf(possibleType, expectedType)) {
|
||||
if (JetTypeChecker.DEFAULT.isSubtypeOf(possibleType, expectedType)) {
|
||||
AutoCastUtils.recordCastOrError(expression, possibleType, trace, dataFlowValue.isStableIdentifier(), false);
|
||||
return possibleType;
|
||||
}
|
||||
|
||||
+2
-2
@@ -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));
|
||||
|
||||
+3
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+13
-17
@@ -100,21 +100,14 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
DataFlowInfo elseDataFlowInfo = context.dataFlowInfo;
|
||||
for (JetWhenEntry whenEntry : expression.getEntries()) {
|
||||
DataFlowInfos infosForCondition = getDataFlowInfosForEntryCondition(
|
||||
whenEntry, context, subjectExpression, subjectType, subjectDataFlowValue);
|
||||
DataFlowInfo dataFlowInfoForEntryBody;
|
||||
if (infosForCondition == null) {
|
||||
dataFlowInfoForEntryBody = elseDataFlowInfo;
|
||||
}
|
||||
else {
|
||||
dataFlowInfoForEntryBody = infosForCondition.thenInfo.and(elseDataFlowInfo);
|
||||
elseDataFlowInfo = elseDataFlowInfo.and(infosForCondition.elseInfo);
|
||||
}
|
||||
whenEntry, context.replaceDataFlowInfo(elseDataFlowInfo), subjectExpression, subjectType, subjectDataFlowValue);
|
||||
elseDataFlowInfo = elseDataFlowInfo.and(infosForCondition.elseInfo);
|
||||
|
||||
JetExpression bodyExpression = whenEntry.getExpression();
|
||||
if (bodyExpression != null) {
|
||||
WritableScope scopeToExtend = newWritableScopeImpl(context, "Scope extended in when entry");
|
||||
ExpressionTypingContext newContext = contextWithExpectedType
|
||||
.replaceScope(scopeToExtend).replaceDataFlowInfo(dataFlowInfoForEntryBody).replaceContextDependency(INDEPENDENT);
|
||||
.replaceScope(scopeToExtend).replaceDataFlowInfo(infosForCondition.thenInfo).replaceContextDependency(INDEPENDENT);
|
||||
CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION;
|
||||
JetTypeInfo typeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
|
||||
scopeToExtend, Collections.singletonList(bodyExpression), coercionStrategy, newContext, context.trace);
|
||||
@@ -141,7 +134,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
return JetTypeInfo.create(null, commonDataFlowInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
private DataFlowInfos getDataFlowInfosForEntryCondition(
|
||||
@NotNull JetWhenEntry whenEntry,
|
||||
@NotNull ExpressionTypingContext context,
|
||||
@@ -149,13 +142,12 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
@NotNull JetType subjectType,
|
||||
@NotNull DataFlowValue subjectDataFlowValue
|
||||
) {
|
||||
JetWhenCondition[] conditions = whenEntry.getConditions();
|
||||
if (whenEntry.isElse()) {
|
||||
return null;
|
||||
return new DataFlowInfos(context.dataFlowInfo);
|
||||
}
|
||||
|
||||
DataFlowInfos infos = null;
|
||||
for (JetWhenCondition condition : conditions) {
|
||||
for (JetWhenCondition condition : whenEntry.getConditions()) {
|
||||
DataFlowInfos conditionInfos = checkWhenCondition(subjectExpression, subjectExpression == null, subjectType, condition,
|
||||
context, subjectDataFlowValue);
|
||||
if (infos != null) {
|
||||
@@ -165,7 +157,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
infos = conditionInfos;
|
||||
}
|
||||
}
|
||||
return infos;
|
||||
return infos != null ? infos : new DataFlowInfos(context.dataFlowInfo);
|
||||
}
|
||||
|
||||
private DataFlowInfos checkWhenCondition(
|
||||
@@ -238,6 +230,10 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
this.thenInfo = thenInfo;
|
||||
this.elseInfo = elseInfo;
|
||||
}
|
||||
|
||||
private DataFlowInfos(DataFlowInfo info) {
|
||||
this(info, info);
|
||||
}
|
||||
}
|
||||
|
||||
private DataFlowInfos checkTypeForExpressionCondition(
|
||||
@@ -258,7 +254,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
context = context.replaceDataFlowInfo(typeInfo.getDataFlowInfo());
|
||||
if (conditionExpected) {
|
||||
JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
|
||||
if (!JetTypeChecker.INSTANCE.equalTypes(booleanType, type)) {
|
||||
if (!JetTypeChecker.DEFAULT.equalTypes(booleanType, type)) {
|
||||
context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(expression, type));
|
||||
}
|
||||
else {
|
||||
@@ -298,7 +294,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
context.trace.report(Errors.USELESS_NULLABLE_CHECK.on(nullableType));
|
||||
}
|
||||
checkTypeCompatibility(context, type, subjectType, typeReferenceAfterIs);
|
||||
if (CastDiagnosticsUtil.isCastErased(subjectType, type, JetTypeChecker.INSTANCE)) {
|
||||
if (CastDiagnosticsUtil.isCastErased(subjectType, type, JetTypeChecker.DEFAULT)) {
|
||||
context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(typeReferenceAfterIs, type));
|
||||
}
|
||||
return new DataFlowInfos(context.dataFlowInfo.establishSubtyping(subjectDataFlowValue, type), context.dataFlowInfo);
|
||||
|
||||
@@ -80,7 +80,7 @@ public class MainFunctionDetector {
|
||||
List<TypeProjection> typeArguments = parameterType.getArguments();
|
||||
if (typeArguments.size() == 1) {
|
||||
JetType typeArgument = typeArguments.get(0).getType();
|
||||
if (JetTypeChecker.INSTANCE.equalTypes(typeArgument, kotlinBuiltIns.getStringType())) {
|
||||
if (JetTypeChecker.DEFAULT.equalTypes(typeArgument, kotlinBuiltIns.getStringType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
|
||||
package org.jetbrains.jet.util.slicedmap;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Slices {
|
||||
private static final Logger LOG = Logger.getInstance(Slices.class);
|
||||
|
||||
public static final RewritePolicy ONLY_REWRITE_TO_EQUAL = new RewritePolicy() {
|
||||
@Override
|
||||
@@ -33,7 +35,7 @@ public class Slices {
|
||||
public <K, V> boolean processRewrite(WritableSlice<K, V> slice, K key, V oldValue, V newValue) {
|
||||
if (!((oldValue == null && newValue == null) || (oldValue != null && oldValue.equals(newValue)))) {
|
||||
// NOTE: Use BindingTraceContext.TRACK_REWRITES to debug this exception
|
||||
throw new IllegalStateException("Rewrite at slice " + slice +
|
||||
LOG.error("Rewrite at slice " + slice +
|
||||
" key: " + key +
|
||||
" old value: " + oldValue + '@' + System.identityHashCode(oldValue) +
|
||||
" new value: " + newValue + '@' + System.identityHashCode(newValue));
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
public final class Derived implements kotlin.jvm.internal.KObject, Base {
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public Derived(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "x") Base x) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
public final class Derived implements kotlin.jvm.internal.KObject, Base {
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public Derived(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "x") Base x) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
|
||||
@@ -34,7 +34,6 @@ public final class Class implements kotlin.jvm.internal.KObject {
|
||||
@org.jetbrains.annotations.Nullable
|
||||
public final java.lang.String getNullableVar() { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "<set-?>", type = "?") java.lang.String p) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
@@ -43,7 +42,6 @@ public final class Class implements kotlin.jvm.internal.KObject {
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final java.lang.String getNotNullVar() { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "<set-?>") java.lang.String p) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.Nullable
|
||||
@@ -55,7 +53,6 @@ public final class Class implements kotlin.jvm.internal.KObject {
|
||||
public final java.lang.String getNotNullVarWithGetSet() { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.Nullable
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final void setNotNullVarWithGetSet(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "v") java.lang.String v) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
@@ -69,6 +66,5 @@ public final class Class implements kotlin.jvm.internal.KObject {
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final void setNullableVarWithGetSet(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "v", type = "?") java.lang.String v) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public Class() { /* compiled code */ }
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ public final class ClassObjectField implements kotlin.jvm.internal.KObject {
|
||||
private static final java.lang.String y = "";
|
||||
public static final ClassObjectField.object object$;
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public ClassObjectField() { /* compiled code */ }
|
||||
|
||||
public static final class object implements kotlin.jvm.internal.KObject {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
public final class ClassWithConstructor implements kotlin.jvm.internal.KObject {
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public ClassWithConstructor(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "nullable", type = "?") java.lang.String nullable, @org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "notNull") java.lang.String notNull) { /* compiled code */ }
|
||||
}
|
||||
|
||||
-1
@@ -10,6 +10,5 @@ public final class ClassWithConstructorAndProperties implements kotlin.jvm.inter
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final java.lang.String getNotNull() { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public ClassWithConstructorAndProperties(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "nullable", type = "?") java.lang.String nullable, @org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "notNull") java.lang.String notNull) { /* compiled code */ }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
public final class C implements kotlin.jvm.internal.KObject, Tr {
|
||||
private final int v = 1;
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public java.lang.Integer foo() { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public java.lang.Integer getV() { /* compiled code */ }
|
||||
|
||||
public C() { /* compiled code */ }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// C
|
||||
|
||||
trait Tr {
|
||||
fun foo(): Any
|
||||
val v: Any
|
||||
}
|
||||
|
||||
class C: Tr {
|
||||
override fun foo() = 1
|
||||
override val v = 1
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
public final class _DefaultPackage {
|
||||
@org.jetbrains.annotations.Nullable
|
||||
public static final kotlin.Unit foo() { /* compiled code */ }
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// _DefaultPackage
|
||||
|
||||
fun foo(): Unit? = null
|
||||
@@ -0,0 +1,5 @@
|
||||
public final class C implements kotlin.jvm.internal.KObject, Base {
|
||||
public void foo() { /* compiled code */ }
|
||||
|
||||
public C() { /* compiled code */ }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// C
|
||||
|
||||
trait Base {
|
||||
fun foo(): Any
|
||||
}
|
||||
|
||||
class C : Base {
|
||||
override fun foo(): Unit {}
|
||||
}
|
||||
@@ -1,14 +1,11 @@
|
||||
public final class Synthetic implements kotlin.jvm.internal.KObject {
|
||||
private final void foo() { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public Synthetic() { /* compiled code */ }
|
||||
|
||||
public final class Inner implements kotlin.jvm.internal.KObject {
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final void test() { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public Inner() { /* compiled code */ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ public interface Trait extends kotlin.jvm.internal.KObject {
|
||||
@org.jetbrains.annotations.Nullable
|
||||
java.lang.String getNullableVar();
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "<set-?>", type = "?") java.lang.String p);
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
@@ -34,6 +33,5 @@ public interface Trait extends kotlin.jvm.internal.KObject {
|
||||
@org.jetbrains.annotations.NotNull
|
||||
java.lang.String getNotNullVar();
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "<set-?>") java.lang.String p);
|
||||
}
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public final class C implements kotlin.jvm.internal.KObject, Base<kotlin.Unit> {
|
||||
public void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "t") kotlin.Unit t) { /* compiled code */ }
|
||||
|
||||
public C() { /* compiled code */ }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// C
|
||||
|
||||
trait Base<T> {
|
||||
fun foo(t: T): T
|
||||
}
|
||||
|
||||
class C : Base<Unit> {
|
||||
override fun foo(t: Unit) {}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
public final class _DefaultPackage {
|
||||
public static final void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "s") kotlin.Unit s) { /* compiled code */ }
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// _DefaultPackage
|
||||
|
||||
fun foo(s: Unit) {}
|
||||
@@ -0,0 +1,3 @@
|
||||
public final class _DefaultPackage {
|
||||
public static final void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "s") java.lang.String s) { /* compiled code */ }
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// _DefaultPackage
|
||||
|
||||
fun foo(s: String) {}
|
||||
@@ -9,7 +9,6 @@ public final class _DefaultPackage {
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public static final java.lang.String getNotNullVar() { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public static final void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "<set-?>") java.lang.String p) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.Nullable
|
||||
@@ -17,7 +16,6 @@ public final class _DefaultPackage {
|
||||
public static final java.lang.String getNotNullVarWithGetSet() { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.Nullable
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public static final void setNotNullVarWithGetSet(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "v") java.lang.String v) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.Nullable
|
||||
@@ -30,7 +28,6 @@ public final class _DefaultPackage {
|
||||
@org.jetbrains.annotations.Nullable
|
||||
public static final java.lang.String getNullableVar() { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public static final void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "<set-?>", type = "?") java.lang.String p) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
|
||||
@@ -14,14 +14,14 @@ L0:
|
||||
2 mark({ val b: Boolean if (1 < 2) { use(b) } else { b = true } })
|
||||
v(val b: Boolean) INIT: in: {} out: {b=D}
|
||||
mark(if (1 < 2) { use(b) } else { b = true }) INIT: in: {b=D} out: {b=D}
|
||||
mark(1 < 2)
|
||||
r(1) -> <v0>
|
||||
r(2) -> <v1>
|
||||
mark(1 < 2)
|
||||
call(<, compareTo|<v0>, <v1>) -> <v2>
|
||||
jf(L2|<v2>)
|
||||
3 mark({ use(b) })
|
||||
mark(use(b)) USE: in: {b=READ} out: {b=READ}
|
||||
3 mark({ use(b) }) USE: in: {b=READ} out: {b=READ}
|
||||
r(b) -> <v3> USE: in: {} out: {b=READ}
|
||||
mark(use(b))
|
||||
call(use, use|<v3>) -> <v4>
|
||||
2 jmp(L3) USE: in: {} out: {}
|
||||
L2:
|
||||
|
||||
@@ -9,18 +9,18 @@ fun foo() {
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
1 <v0> NEW()
|
||||
2 <v1> NEW()
|
||||
1 < 2 <v2> NEW(<v0>, <v1>)
|
||||
b <v3> NEW()
|
||||
use(b) <v4> NEW(<v3>)
|
||||
{ use(b) } <v4> COPY
|
||||
true <v5> NEW()
|
||||
if (1 < 2) { use(b) } else { b = true } <v4> COPY
|
||||
{ val b: Boolean if (1 < 2) { use(b) } else { b = true } } <v4> COPY
|
||||
1 <v0>: {<: Comparable<Int>} NEW()
|
||||
2 <v1>: Int NEW()
|
||||
1 < 2 <v2>: Boolean NEW(<v0>, <v1>)
|
||||
b <v3>: {<: Any?} NEW()
|
||||
use(b) <v4>: * NEW(<v3>)
|
||||
{ use(b) } <v4>: * COPY
|
||||
true <v5>: Boolean NEW()
|
||||
if (1 < 2) { use(b) } else { b = true } <v4>: * COPY
|
||||
{ val b: Boolean if (1 < 2) { use(b) } else { b = true } } <v4>: * COPY
|
||||
=====================
|
||||
== use ==
|
||||
fun use(vararg a: Any?) = a
|
||||
---------------------
|
||||
a <v1> NEW()
|
||||
a <v1>: {<: Array<Any?>} NEW()
|
||||
=====================
|
||||
|
||||
@@ -6,5 +6,5 @@ class A {
|
||||
val x: Int
|
||||
}
|
||||
---------------------
|
||||
1 <v1> NEW()
|
||||
1 <v1>: Int NEW()
|
||||
=====================
|
||||
|
||||
@@ -39,14 +39,14 @@ L3:
|
||||
magic(x: Int) -> <v0> INIT: in: {x=D} out: {x=D}
|
||||
w(x|<v0>) INIT: in: {x=D} out: {x=ID}
|
||||
4 mark(val y = x + a use(a)) INIT: in: {x=ID} out: {x=ID}
|
||||
v(val y = x + a) INIT: in: {x=ID} out: {x=ID, y=D}
|
||||
mark(x + a) INIT: in: {x=ID, y=D} out: {x=ID, y=D} USE: in: {a=READ, x=READ} out: {a=READ, x=READ}
|
||||
r(x) -> <v1> USE: in: {a=READ} out: {a=READ, x=READ}
|
||||
v(val y = x + a) INIT: in: {x=ID} out: {x=ID, y=D} USE: in: {a=READ, x=READ} out: {a=READ, x=READ}
|
||||
r(x) -> <v1> INIT: in: {x=ID, y=D} out: {x=ID, y=D} USE: in: {a=READ} out: {a=READ, x=READ}
|
||||
r(a) -> <v2>
|
||||
mark(x + a)
|
||||
call(+, plus|<v1>, <v2>) -> <v3>
|
||||
w(y|<v3>) INIT: in: {x=ID, y=D} out: {x=ID, y=ID}
|
||||
mark(use(a)) INIT: in: {x=ID, y=ID} out: {x=ID, y=ID} USE: in: {a=READ} out: {a=READ}
|
||||
r(a) -> <v4> USE: in: {} out: {a=READ}
|
||||
w(y|<v3>) INIT: in: {x=ID, y=D} out: {x=ID, y=ID} USE: in: {a=READ} out: {a=READ}
|
||||
r(a) -> <v4> INIT: in: {x=ID, y=ID} out: {x=ID, y=ID} USE: in: {} out: {a=READ}
|
||||
mark(use(a))
|
||||
call(use, use|<v4>) -> <v5>
|
||||
L4:
|
||||
3 <END> INIT: in: {x=ID} out: {x=ID}
|
||||
|
||||
@@ -7,8 +7,8 @@ fun foo() {
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
1 <v0> NEW()
|
||||
{ (x: Int) -> val y = x + a use(a) } <v1> NEW()
|
||||
1 <v0>: Int NEW()
|
||||
{ (x: Int) -> val y = x + a use(a) } <v1>: {<: (Int) -> Array<Any?>} NEW()
|
||||
=====================
|
||||
== anonymous_0 ==
|
||||
{ (x: Int) ->
|
||||
@@ -16,15 +16,15 @@ fun foo() {
|
||||
use(a)
|
||||
}
|
||||
---------------------
|
||||
x <v1> NEW()
|
||||
a <v2> NEW()
|
||||
x + a <v3> NEW(<v1>, <v2>)
|
||||
a <v4> NEW()
|
||||
use(a) <v5> NEW(<v4>)
|
||||
val y = x + a use(a) <v5> COPY
|
||||
x <v1>: Int NEW()
|
||||
a <v2>: Int NEW()
|
||||
x + a <v3>: Int NEW(<v1>, <v2>)
|
||||
a <v4>: {<: Any?} NEW()
|
||||
use(a) <v5>: {<: Array<Any?>} NEW(<v4>)
|
||||
val y = x + a use(a) <v5>: {<: Array<Any?>} COPY
|
||||
=====================
|
||||
== use ==
|
||||
fun use(vararg a: Any?) = a
|
||||
---------------------
|
||||
a <v1> NEW()
|
||||
a <v1>: {<: Array<Any?>} NEW()
|
||||
=====================
|
||||
|
||||
@@ -6,10 +6,10 @@ fun foo() {
|
||||
42
|
||||
}
|
||||
---------------------
|
||||
1 <v0> NEW()
|
||||
2 <v1> NEW()
|
||||
42 <v2> NEW()
|
||||
{ val a = 1 val b: Int b = 2 42 } <v2> COPY
|
||||
1 <v0>: Int NEW()
|
||||
2 <v1>: Int NEW()
|
||||
42 <v2>: * NEW()
|
||||
{ val a = 1 val b: Int b = 2 42 } <v2>: * COPY
|
||||
=====================
|
||||
== bar ==
|
||||
fun bar(foo: Foo) {
|
||||
@@ -18,13 +18,13 @@ fun bar(foo: Foo) {
|
||||
42
|
||||
}
|
||||
---------------------
|
||||
foo <v1> NEW()
|
||||
c <v2> NEW(<v1>)
|
||||
foo.c <v2> COPY
|
||||
foo <v3> NEW()
|
||||
2 <v4> NEW()
|
||||
42 <v5> NEW()
|
||||
{ foo.c foo.c = 2 42 } <v5> COPY
|
||||
foo <v1>: {<: Foo} NEW()
|
||||
c <v2>: * NEW(<v1>)
|
||||
foo.c <v2>: * COPY
|
||||
foo <v3>: {<: Foo} NEW()
|
||||
2 <v4>: Int NEW()
|
||||
42 <v5>: * NEW()
|
||||
{ foo.c foo.c = 2 42 } <v5>: * COPY
|
||||
=====================
|
||||
== Foo ==
|
||||
trait Foo {
|
||||
|
||||
@@ -11,14 +11,14 @@ L0:
|
||||
2 mark({ var a = 1 use(a) a = 2 use(a) })
|
||||
v(var a = 1) INIT: in: {} out: {a=D}
|
||||
r(1) -> <v0> INIT: in: {a=D} out: {a=D}
|
||||
w(a|<v0>) INIT: in: {a=D} out: {a=ID}
|
||||
mark(use(a)) INIT: in: {a=ID} out: {a=ID} USE: in: {a=READ} out: {a=READ}
|
||||
r(a) -> <v1> USE: in: {a=WRITTEN_AFTER_READ} out: {a=READ}
|
||||
w(a|<v0>) INIT: in: {a=D} out: {a=ID} USE: in: {a=READ} out: {a=READ}
|
||||
r(a) -> <v1> INIT: in: {a=ID} out: {a=ID} USE: in: {a=WRITTEN_AFTER_READ} out: {a=READ}
|
||||
mark(use(a))
|
||||
call(use, use|<v1>) -> <v2>
|
||||
r(2) -> <v3> USE: in: {a=WRITTEN_AFTER_READ} out: {a=WRITTEN_AFTER_READ}
|
||||
w(a|<v3>) USE: in: {a=READ} out: {a=WRITTEN_AFTER_READ}
|
||||
mark(use(a)) USE: in: {a=READ} out: {a=READ}
|
||||
r(a) -> <v4> USE: in: {} out: {a=READ}
|
||||
mark(use(a))
|
||||
call(use, use|<v4>) -> <v5>
|
||||
L1:
|
||||
1 <END> INIT: in: {} out: {}
|
||||
|
||||
@@ -6,13 +6,13 @@ fun foo() {
|
||||
use(a)
|
||||
}
|
||||
---------------------
|
||||
1 <v0> NEW()
|
||||
a <v1> NEW()
|
||||
use(a) <v2> NEW(<v1>)
|
||||
2 <v3> NEW()
|
||||
a <v4> NEW()
|
||||
use(a) <v5> NEW(<v4>)
|
||||
{ var a = 1 use(a) a = 2 use(a) } <v5> COPY
|
||||
1 <v0>: Int NEW()
|
||||
a <v1>: Int NEW()
|
||||
use(a) <v2>: * NEW(<v1>)
|
||||
2 <v3>: Int NEW()
|
||||
a <v4>: Int NEW()
|
||||
use(a) <v5>: * NEW(<v4>)
|
||||
{ var a = 1 use(a) a = 2 use(a) } <v5>: * COPY
|
||||
=====================
|
||||
== bar ==
|
||||
fun bar() {
|
||||
@@ -20,10 +20,10 @@ fun bar() {
|
||||
b = 3
|
||||
}
|
||||
---------------------
|
||||
3 <v0> NEW()
|
||||
3 <v0>: Int NEW()
|
||||
=====================
|
||||
== use ==
|
||||
fun use(a: Int) = a
|
||||
---------------------
|
||||
a <v1> NEW()
|
||||
a <v1>: Int NEW()
|
||||
=====================
|
||||
|
||||
@@ -32,16 +32,16 @@ L3:
|
||||
magic(x: Int) -> <v0> INIT: in: {x=D} out: {x=D}
|
||||
w(x|<v0>) INIT: in: {x=D} out: {x=ID}
|
||||
3 mark(sum(x - 1) + x) INIT: in: {x=ID} out: {x=ID}
|
||||
mark(sum(x - 1) + x)
|
||||
mark(sum(x - 1))
|
||||
magic(sum) -> <v1> USE: in: {sum=READ, x=READ} out: {sum=READ, x=READ}
|
||||
r(sum|<v1>) -> <v2> USE: in: {x=READ} out: {sum=READ, x=READ}
|
||||
mark(x - 1)
|
||||
r(x) -> <v3>
|
||||
r(1) -> <v4>
|
||||
mark(x - 1)
|
||||
call(-, minus|<v3>, <v4>) -> <v5>
|
||||
mark(sum(x - 1))
|
||||
call(sum, invoke|<v2>, <v5>) -> <v6> USE: in: {x=READ} out: {x=READ}
|
||||
r(x) -> <v7> USE: in: {} out: {x=READ}
|
||||
mark(sum(x - 1) + x)
|
||||
call(+, plus|<v6>, <v7>) -> <v8>
|
||||
L4:
|
||||
2 <END>
|
||||
@@ -127,10 +127,10 @@ class TestOther {
|
||||
L0:
|
||||
1 <START> INIT: in: {} out: {}
|
||||
v(val x: Int = x + 1) INIT: in: {} out: {x=D}
|
||||
mark(x + 1) INIT: in: {x=D} out: {x=D}
|
||||
magic(x) -> <v0> USE: in: {x=READ} out: {x=READ}
|
||||
magic(x) -> <v0> INIT: in: {x=D} out: {x=D} USE: in: {x=READ} out: {x=READ}
|
||||
r(x|<v0>) -> <v1> USE: in: {} out: {x=READ}
|
||||
r(1) -> <v2>
|
||||
mark(x + 1)
|
||||
call(+, plus|<v1>, <v2>) -> <v3>
|
||||
w(x|<v3>) INIT: in: {x=D} out: {x=ID}
|
||||
L1:
|
||||
|
||||
@@ -5,21 +5,21 @@ class TestFunctionLiteral {
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
{ (x: Int) -> sum(x - 1) + x } <v0> NEW()
|
||||
{ (x: Int) -> sum(x - 1) + x } <v0>: {<: (Int) -> Int} NEW()
|
||||
=====================
|
||||
== anonymous_0 ==
|
||||
{ (x: Int) ->
|
||||
sum(x - 1) + x
|
||||
}
|
||||
---------------------
|
||||
sum <v2> NEW(<v1>)
|
||||
x <v3> NEW()
|
||||
1 <v4> NEW()
|
||||
x - 1 <v5> NEW(<v3>, <v4>)
|
||||
sum(x - 1) <v6> NEW(<v2>, <v5>)
|
||||
x <v7> NEW()
|
||||
sum(x - 1) + x <v8> NEW(<v6>, <v7>)
|
||||
sum(x - 1) + x <v8> COPY
|
||||
sum <v2>: {<: (Int) -> Int} NEW(<v1>)
|
||||
x <v3>: Int NEW()
|
||||
1 <v4>: Int NEW()
|
||||
x - 1 <v5>: Int NEW(<v3>, <v4>)
|
||||
sum(x - 1) <v6>: Int NEW(<v2>, <v5>)
|
||||
x <v7>: Int NEW()
|
||||
sum(x - 1) + x <v8>: Int NEW(<v6>, <v7>)
|
||||
sum(x - 1) + x <v8>: Int COPY
|
||||
=====================
|
||||
== A ==
|
||||
open class A(val a: A)
|
||||
@@ -37,23 +37,23 @@ class TestObjectLiteral {
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
obj <v1> NEW(<v0>)
|
||||
obj <v3> NEW(<v2>)
|
||||
object: A(obj) { { val x = obj } fun foo() { val y = obj } } <v4> NEW()
|
||||
obj <v1>: * NEW(<v0>)
|
||||
obj <v3>: {<: A} NEW(<v2>)
|
||||
object: A(obj) { { val x = obj } fun foo() { val y = obj } } <v4>: {<: A} NEW()
|
||||
=====================
|
||||
== foo ==
|
||||
fun foo() {
|
||||
val y = obj
|
||||
}
|
||||
---------------------
|
||||
obj <v1> NEW(<v0>)
|
||||
obj <v1>: {<: A} NEW(<v0>)
|
||||
=====================
|
||||
== TestOther ==
|
||||
class TestOther {
|
||||
val x: Int = x + 1
|
||||
}
|
||||
---------------------
|
||||
x <v1> NEW(<v0>)
|
||||
1 <v2> NEW()
|
||||
x + 1 <v3> NEW(<v1>, <v2>)
|
||||
x <v1>: Int NEW(<v0>)
|
||||
1 <v2>: Int NEW()
|
||||
x + 1 <v3>: Int NEW(<v1>, <v2>)
|
||||
=====================
|
||||
|
||||
@@ -15,9 +15,9 @@ L0:
|
||||
2 mark({ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) })
|
||||
v(val b: Boolean) INIT: in: {} out: {b=D}
|
||||
mark(if (1 < 2) { b = false } else { b = true }) INIT: in: {b=D} out: {b=D}
|
||||
mark(1 < 2)
|
||||
r(1) -> <v0>
|
||||
r(2) -> <v1>
|
||||
mark(1 < 2)
|
||||
call(<, compareTo|<v0>, <v1>) -> <v2>
|
||||
jf(L2|<v2>)
|
||||
3 mark({ b = false })
|
||||
@@ -29,10 +29,10 @@ L2:
|
||||
r(true) -> <v4> USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ}
|
||||
w(b|<v4>) INIT: in: {b=D} out: {b=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ}
|
||||
L3:
|
||||
2 mark(use(b)) INIT: in: {b=ID} out: {b=ID}
|
||||
error(use, No resolved call) USE: in: {b=READ} out: {b=READ}
|
||||
2 error(use, No resolved call) INIT: in: {b=ID} out: {b=ID} USE: in: {b=READ} out: {b=READ}
|
||||
r(b) -> <v5> USE: in: {} out: {b=READ}
|
||||
error(use, No resolved call)
|
||||
mark(use(b))
|
||||
magic(use(b)|<v5>) -> <v6>
|
||||
L1:
|
||||
1 <END> INIT: in: {} out: {}
|
||||
|
||||
@@ -10,12 +10,12 @@ fun foo() {
|
||||
use(b)
|
||||
}
|
||||
---------------------
|
||||
1 <v0> NEW()
|
||||
2 <v1> NEW()
|
||||
1 < 2 <v2> NEW(<v0>, <v1>)
|
||||
false <v3> NEW()
|
||||
true <v4> NEW()
|
||||
b <v5> NEW()
|
||||
use(b) <v6> NEW(<v5>)
|
||||
{ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) } <v6> COPY
|
||||
1 <v0>: {<: Comparable<Int>} NEW()
|
||||
2 <v1>: Int NEW()
|
||||
1 < 2 <v2>: Boolean NEW(<v0>, <v1>)
|
||||
false <v3>: Boolean NEW()
|
||||
true <v4>: Boolean NEW()
|
||||
b <v5>: * NEW()
|
||||
use(b) <v6>: * NEW(<v5>)
|
||||
{ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) } <v6>: * COPY
|
||||
=====================
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user