Merge branch 'master' of github.com:JetBrains/kotlin
This commit is contained in:
@@ -22,6 +22,7 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
@@ -118,7 +119,7 @@ public class ClosureAnnotator {
|
||||
}
|
||||
|
||||
public boolean hasThis0(ClassDescriptor classDescriptor) {
|
||||
if(CodegenUtil.isClassObject(classDescriptor))
|
||||
if(DescriptorUtils.isClassObject(classDescriptor))
|
||||
return false;
|
||||
|
||||
ClassDescriptor other = enclosing.get(classDescriptor);
|
||||
|
||||
@@ -42,21 +42,6 @@ public class CodegenUtil {
|
||||
public static boolean isInterface(JetType type) {
|
||||
return isInterface(type.getConstructor().getDeclarationDescriptor());
|
||||
}
|
||||
|
||||
public static boolean isClassObject(DeclarationDescriptor descriptor) {
|
||||
if(descriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
|
||||
if(classDescriptor.getKind() == ClassKind.OBJECT) {
|
||||
if(classDescriptor.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||
ClassDescriptor containingDeclaration = (ClassDescriptor) classDescriptor.getContainingDeclaration();
|
||||
if(classDescriptor.getDefaultType().equals(containingDeclaration.getClassObjectType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static SimpleFunctionDescriptor createInvoke(FunctionDescriptor fd) {
|
||||
int arity = fd.getValueParameters().size();
|
||||
|
||||
@@ -1021,7 +1021,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL ;
|
||||
JetExpression r = getReceiverForSelector(expression);
|
||||
final boolean isSuper = r instanceof JetSuperExpression;
|
||||
if(propertyDescriptor.getVisibility() == Visibilities.PRIVATE && !CodegenUtil.isClassObject(propertyDescriptor.getContainingDeclaration())) {
|
||||
if(propertyDescriptor.getVisibility() == Visibilities.PRIVATE && !DescriptorUtils
|
||||
.isClassObject(propertyDescriptor.getContainingDeclaration())) {
|
||||
if(context.getClassOrNamespaceDescriptor() != propertyDescriptor.getContainingDeclaration()) {
|
||||
DeclarationDescriptor enclosed = propertyDescriptor.getContainingDeclaration();
|
||||
if(enclosed != null && enclosed != context.getThisDescriptor()) {
|
||||
@@ -1374,7 +1375,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
Type exprType = asmType(descriptor.getType());
|
||||
ClassReceiver classReceiver = (ClassReceiver) descriptor;
|
||||
ClassDescriptor classReceiverDeclarationDescriptor = (ClassDescriptor) classReceiver.getDeclarationDescriptor();
|
||||
if(CodegenUtil.isClassObject(classReceiverDeclarationDescriptor)) {
|
||||
if(DescriptorUtils.isClassObject(classReceiverDeclarationDescriptor)) {
|
||||
ClassDescriptor containingDeclaration = (ClassDescriptor) classReceiverDeclarationDescriptor.getContainingDeclaration();
|
||||
Type classObjType = typeMapper.mapType(containingDeclaration.getDefaultType(), MapTypeMode.IMPL);
|
||||
v.getstatic(classObjType.getInternalName(), "$classobj", exprType.getDescriptor());
|
||||
|
||||
@@ -835,7 +835,7 @@ public class JetTypeMapper {
|
||||
return ACC_PROTECTED;
|
||||
}
|
||||
else if (p.getVisibility() == Visibilities.PRIVATE) {
|
||||
if(CodegenUtil.isClassObject(declaration)) {
|
||||
if(DescriptorUtils.isClassObject(declaration)) {
|
||||
return defaultFlags;
|
||||
}
|
||||
return ACC_PRIVATE;
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||
@@ -121,7 +122,7 @@ public class PropertyCodegen {
|
||||
}
|
||||
|
||||
private static boolean isExternallyAccessible(PropertyDescriptor p) {
|
||||
return p.getVisibility() != Visibilities.PRIVATE || CodegenUtil.isClassObject(p.getContainingDeclaration());
|
||||
return p.getVisibility() != Visibilities.PRIVATE || DescriptorUtils.isClassObject(p.getContainingDeclaration());
|
||||
}
|
||||
|
||||
private void generateSetter(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||
|
||||
+2
-2
@@ -1394,7 +1394,7 @@ public class JavaDescriptorResolver {
|
||||
if (owner instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) owner;
|
||||
|
||||
OverrideResolver.generateOverridesInFunctionGroup(propertyName, propertiesFromSupertypes, propertiesFromCurrent, classDescriptor, new OverrideResolver.DescriptorSink() {
|
||||
OverrideResolver.generateOverridesInFunctionGroup(propertyName, null, propertiesFromSupertypes, propertiesFromCurrent, classDescriptor, new OverrideResolver.DescriptorSink() {
|
||||
@Override
|
||||
public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
|
||||
properties.add((PropertyDescriptor) fakeOverride);
|
||||
@@ -1433,7 +1433,7 @@ public class JavaDescriptorResolver {
|
||||
|
||||
Set<SimpleFunctionDescriptor> functionsFromSupertypes = getFunctionsFromSupertypes(scopeData, methodName);
|
||||
|
||||
OverrideResolver.generateOverridesInFunctionGroup(methodName, functionsFromSupertypes, functionsFromCurrent, classDescriptor, new OverrideResolver.DescriptorSink() {
|
||||
OverrideResolver.generateOverridesInFunctionGroup(methodName, null, functionsFromSupertypes, functionsFromCurrent, classDescriptor, new OverrideResolver.DescriptorSink() {
|
||||
@Override
|
||||
public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
|
||||
functions.add((FunctionDescriptor) fakeOverride);
|
||||
|
||||
@@ -106,6 +106,10 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorImpl i
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setVisibility(@NotNull Visibility visibility) {
|
||||
this.visibility = visibility;
|
||||
}
|
||||
|
||||
public void setReturnType(@NotNull JetType unsubstitutedReturnType) {
|
||||
this.unsubstitutedReturnType = unsubstitutedReturnType;
|
||||
}
|
||||
|
||||
+5
-1
@@ -34,9 +34,9 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm
|
||||
private final boolean hasBody;
|
||||
private final boolean isDefault;
|
||||
private final Modality modality;
|
||||
private final Visibility visibility;
|
||||
private final PropertyDescriptor correspondingProperty;
|
||||
private final Kind kind;
|
||||
private Visibility visibility;
|
||||
|
||||
public PropertyAccessorDescriptor(
|
||||
@NotNull Modality modality,
|
||||
@@ -99,6 +99,10 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm
|
||||
return visibility;
|
||||
}
|
||||
|
||||
public void setVisibility(Visibility visibility) {
|
||||
this.visibility = visibility;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PropertyDescriptor getCorrespondingProperty() {
|
||||
return correspondingProperty;
|
||||
|
||||
@@ -131,6 +131,10 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
public void setVisibility(@NotNull Visibility visibility) {
|
||||
this.visibility = visibility;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<TypeParameterDescriptor> getTypeParameters() {
|
||||
|
||||
@@ -32,11 +32,14 @@ public class Visibilities {
|
||||
public static final Visibility PRIVATE = new Visibility("private", false) {
|
||||
@Override
|
||||
protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
|
||||
if (what instanceof CallableMemberDescriptor && ((CallableMemberDescriptor)what).getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||
return false;
|
||||
}
|
||||
DeclarationDescriptor parent = what;
|
||||
while (parent != null) {
|
||||
parent = parent.getContainingDeclaration();
|
||||
if ((parent instanceof ClassDescriptor && ((ClassDescriptor)parent).getKind() != ClassKind.OBJECT) ||
|
||||
parent instanceof NamespaceDescriptor) {
|
||||
if ((parent instanceof ClassDescriptor && !DescriptorUtils.isClassObject(parent)) ||
|
||||
parent instanceof NamespaceDescriptor) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -93,7 +96,14 @@ public class Visibilities {
|
||||
public static final Visibility LOCAL = new Visibility("local", false) {
|
||||
@Override
|
||||
protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
|
||||
return true;
|
||||
throw new IllegalStateException(); //This method shouldn't be invoked for LOCAL visibility
|
||||
}
|
||||
};
|
||||
|
||||
public static final Visibility INHERITED = new Visibility("inherited", false) {
|
||||
@Override
|
||||
protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
|
||||
throw new IllegalStateException("Visibility is unknown yet"); //This method shouldn't be invoked for INHERITED visibility
|
||||
}
|
||||
};
|
||||
|
||||
@@ -102,6 +112,9 @@ public class Visibilities {
|
||||
public static boolean isVisible(DeclarationDescriptorWithVisibility what, DeclarationDescriptor from) {
|
||||
DeclarationDescriptorWithVisibility parent = what;
|
||||
while (parent != null) {
|
||||
if (parent.getVisibility() == LOCAL) {
|
||||
return true;
|
||||
}
|
||||
if (!parent.getVisibility().isVisible(parent, from)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -157,7 +157,10 @@ public interface Errors {
|
||||
DiagnosticFactory<JetDelegatorToSuperClass> INITIALIZER_WITH_NO_ARGUMENTS = DiagnosticFactory.create(ERROR, "Constructor arguments required");
|
||||
DiagnosticFactory<JetDelegationSpecifier> MANY_CALLS_TO_THIS = DiagnosticFactory.create(ERROR, "Only one call to 'this(...)' is allowed");
|
||||
DiagnosticFactory1<JetModifierListOwner, CallableMemberDescriptor> NOTHING_TO_OVERRIDE = DiagnosticFactory1.create(ERROR, "{0} overrides nothing", PositioningStrategies.positionModifier(JetTokens.OVERRIDE_KEYWORD), DescriptorRenderer.TEXT);
|
||||
DiagnosticFactory3<PsiNameIdentifierOwner, CallableMemberDescriptor, CallableMemberDescriptor, DeclarationDescriptor> VIRTUAL_MEMBER_HIDDEN = DiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier", PositioningStrategies.POSITION_NAME_IDENTIFIER, DescriptorRenderer.TEXT, DescriptorRenderer.TEXT, DescriptorRenderer.TEXT);
|
||||
DiagnosticFactory3<PsiNameIdentifierOwner, CallableMemberDescriptor, CallableMemberDescriptor, DeclarationDescriptor> VIRTUAL_MEMBER_HIDDEN =
|
||||
DiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier", PositioningStrategies.POSITION_NAME_IDENTIFIER, DescriptorRenderer.TEXT, DescriptorRenderer.TEXT, DescriptorRenderer.TEXT);
|
||||
DiagnosticFactory3<JetModifierListOwner, CallableMemberDescriptor, CallableDescriptor, DeclarationDescriptor> CANNOT_OVERRIDE_INVISIBLE_MEMBER =
|
||||
DiagnosticFactory3.create(ERROR, "''{0}'' cannot has no access to ''{1}'' in class {2}, so it cannot override it", PositioningStrategies.positionModifier(JetTokens.OVERRIDE_KEYWORD), DescriptorRenderer.TEXT, DescriptorRenderer.TEXT, DescriptorRenderer.TEXT);
|
||||
|
||||
DiagnosticFactory1<JetClass, ClassDescriptor> ENUM_ENTRY_SHOULD_BE_INITIALIZED = DiagnosticFactory1.create(ERROR, "Missing delegation specifier ''{0}''", PositioningStrategies.POSITION_NAME_IDENTIFIER, NAME);
|
||||
DiagnosticFactory1<JetTypeReference, ClassDescriptor> ENUM_ENTRY_ILLEGAL_TYPE = DiagnosticFactory1.create(ERROR, "The type constructor of enum entry should be ''{0}''", NAME);
|
||||
|
||||
@@ -223,7 +223,7 @@ public class DeclarationResolver {
|
||||
parameter, trace
|
||||
);
|
||||
classDescriptor.addPropertyDescriptor(propertyDescriptor);
|
||||
context.getPrimaryConstructorParameterProperties().add(propertyDescriptor);
|
||||
context.getPrimaryConstructorParameterProperties().put(parameter, propertyDescriptor);
|
||||
}
|
||||
}
|
||||
if (constructorDescriptor != null) {
|
||||
|
||||
@@ -673,7 +673,8 @@ public class DescriptorResolver {
|
||||
|
||||
@NotNull
|
||||
/*package*/ static Visibility resolveVisibilityFromModifiers(@Nullable JetModifierList modifierList) {
|
||||
return resolveVisibilityFromModifiers(modifierList, Visibilities.INTERNAL);
|
||||
Visibility defaultVisibility = modifierList != null && modifierList.hasModifier(JetTokens.OVERRIDE_KEYWORD) ? Visibilities.INHERITED : Visibilities.INTERNAL;
|
||||
return resolveVisibilityFromModifiers(modifierList, defaultVisibility);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -314,4 +314,18 @@ public class DescriptorUtils {
|
||||
return namespaceDescriptor.getContainingDeclaration() instanceof ModuleDescriptor;
|
||||
}
|
||||
|
||||
public static boolean isClassObject(@NotNull DeclarationDescriptor descriptor) {
|
||||
if(descriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
|
||||
if(classDescriptor.getKind() == ClassKind.OBJECT) {
|
||||
if(classDescriptor.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||
ClassDescriptor containingDeclaration = (ClassDescriptor) classDescriptor.getContainingDeclaration();
|
||||
if(classDescriptor.getDefaultType().equals(containingDeclaration.getClassObjectType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,14 +16,13 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.*;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.containers.LinkedMultiMap;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -67,15 +66,26 @@ public class OverrideResolver {
|
||||
|
||||
|
||||
public void process() {
|
||||
generateOverrides();
|
||||
checkOverrides();
|
||||
checkVisibilityForOverriddenMembers();
|
||||
//all created fake descriptors are stored to resolve visibility on them later
|
||||
Set<CallableMemberDescriptor> fakeOverrides = Sets.newHashSet();
|
||||
generateOverrides(fakeOverrides);
|
||||
|
||||
//functions and properties visibility can be inherited when overriding, so for overridden members
|
||||
//it can be resolved only after overrides resolve is finished
|
||||
resolveUnknownVisibilityForMembers(fakeOverrides);
|
||||
|
||||
//invisible overridden descriptors are saved for proper error reporting
|
||||
Multimap<CallableDescriptor, CallableDescriptor> invisibleOverriddenDescriptors = LinkedHashMultimap.create();
|
||||
removeInvisibleOverriddenDescriptors(invisibleOverriddenDescriptors);
|
||||
|
||||
checkVisibility();
|
||||
checkOverrides(invisibleOverriddenDescriptors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate fake overrides and add overriden descriptors to existing descriptors.
|
||||
* Generate fake overrides and add overridden descriptors to existing descriptors.
|
||||
*/
|
||||
private void generateOverrides() {
|
||||
private void generateOverrides(@NotNull Set<CallableMemberDescriptor> fakeOverrides) {
|
||||
Set<MutableClassDescriptor> ourClasses = new HashSet<MutableClassDescriptor>();
|
||||
ourClasses.addAll(context.getClasses().values());
|
||||
ourClasses.addAll(context.getObjects().values());
|
||||
@@ -83,11 +93,12 @@ public class OverrideResolver {
|
||||
Set<ClassifierDescriptor> processed = new HashSet<ClassifierDescriptor>();
|
||||
|
||||
for (MutableClassDescriptor clazz : ourClasses) {
|
||||
generateOverridesInAClass(clazz, processed, ourClasses);
|
||||
generateOverridesInAClass(clazz, processed, ourClasses, fakeOverrides);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateOverridesInAClass(final MutableClassDescriptor classDescriptor, Set<ClassifierDescriptor> processed, Set<MutableClassDescriptor> ourClasses) {
|
||||
private void generateOverridesInAClass(@NotNull final MutableClassDescriptor classDescriptor, @NotNull Set<ClassifierDescriptor> processed,
|
||||
@NotNull Set<MutableClassDescriptor> ourClasses, @NotNull Set<CallableMemberDescriptor> fakeOverrides) {
|
||||
if (!processed.add(classDescriptor)) {
|
||||
return;
|
||||
}
|
||||
@@ -100,7 +111,7 @@ public class OverrideResolver {
|
||||
for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
|
||||
ClassDescriptor superclass = (ClassDescriptor) supertype.getConstructor().getDeclarationDescriptor();
|
||||
if (superclass instanceof MutableClassDescriptor) {
|
||||
generateOverridesInAClass((MutableClassDescriptor) superclass, processed, ourClasses);
|
||||
generateOverridesInAClass((MutableClassDescriptor) superclass, processed, ourClasses, fakeOverrides);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +126,7 @@ public class OverrideResolver {
|
||||
functionNames.addAll(functionsFromCurrentByName.keySet());
|
||||
|
||||
for (String functionName : functionNames) {
|
||||
generateOverridesInFunctionGroup(functionName,
|
||||
generateOverridesInFunctionGroup(functionName, fakeOverrides,
|
||||
functionsFromSupertypesByName.get(functionName),
|
||||
functionsFromCurrentByName.get(functionName),
|
||||
classDescriptor,
|
||||
@@ -150,18 +161,15 @@ public class OverrideResolver {
|
||||
|
||||
public static void generateOverridesInFunctionGroup(
|
||||
@NotNull String name,
|
||||
@Nullable Set<CallableMemberDescriptor> fakeOverrides,
|
||||
@NotNull Collection<? extends CallableMemberDescriptor> functionsFromSupertypes,
|
||||
@NotNull Collection<? extends CallableMemberDescriptor> functionsFromCurrent,
|
||||
@NotNull ClassDescriptor current,
|
||||
@NotNull DescriptorSink sink) {
|
||||
|
||||
List<CallableMemberDescriptor> fakeOverrides = Lists.newArrayList();
|
||||
List<CallableMemberDescriptor> fakeOverrideList = Lists.newArrayList();
|
||||
|
||||
for (CallableMemberDescriptor functionFromSupertype : functionsFromSupertypes) {
|
||||
if (!Visibilities.isVisible(functionFromSupertype, current)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean overrides = false;
|
||||
|
||||
for (CallableMemberDescriptor functionFromCurrent : functionsFromCurrent) {
|
||||
@@ -175,7 +183,7 @@ public class OverrideResolver {
|
||||
}
|
||||
}
|
||||
|
||||
for (CallableMemberDescriptor fakeOverride : fakeOverrides) {
|
||||
for (CallableMemberDescriptor fakeOverride : fakeOverrideList) {
|
||||
if (OverridingUtil.isOverridableBy(functionFromSupertype, fakeOverride).getResult() == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE) {
|
||||
fakeOverride.addOverriddenDescriptor(functionFromSupertype);
|
||||
overrides = true;
|
||||
@@ -185,9 +193,10 @@ public class OverrideResolver {
|
||||
if (!overrides) {
|
||||
CallableMemberDescriptor fakeOverride = functionFromSupertype.copy(current, false, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false);
|
||||
fakeOverride.addOverriddenDescriptor(functionFromSupertype);
|
||||
|
||||
fakeOverrides.add(fakeOverride);
|
||||
|
||||
fakeOverrideList.add(fakeOverride);
|
||||
if (fakeOverrides != null) {
|
||||
fakeOverrides.add(fakeOverride);
|
||||
}
|
||||
sink.addToScope(fakeOverride);
|
||||
}
|
||||
}
|
||||
@@ -222,21 +231,22 @@ public class OverrideResolver {
|
||||
return r;
|
||||
}
|
||||
|
||||
private void checkOverrides() {
|
||||
private void checkOverrides(@NotNull Multimap<CallableDescriptor, CallableDescriptor> invisibleOverriddenDescriptors) {
|
||||
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
|
||||
checkOverridesInAClass(entry.getValue(), entry.getKey());
|
||||
checkOverridesInAClass(entry.getValue(), entry.getKey(), invisibleOverriddenDescriptors);
|
||||
}
|
||||
for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
|
||||
checkOverridesInAClass(entry.getValue(), entry.getKey());
|
||||
checkOverridesInAClass(entry.getValue(), entry.getKey(), invisibleOverriddenDescriptors);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) {
|
||||
protected void checkOverridesInAClass(@NotNull MutableClassDescriptor classDescriptor, @NotNull JetClassOrObject klass,
|
||||
@NotNull Multimap<CallableDescriptor, CallableDescriptor> invisibleOverriddenDescriptors) {
|
||||
if (topDownAnalysisParameters.isAnalyzingBootstrapLibrary()) return;
|
||||
|
||||
// Check overrides for internal consistency
|
||||
for (CallableMemberDescriptor member : classDescriptor.getCallableMembers()) {
|
||||
checkOverride(member);
|
||||
checkOverrideForMember(member, invisibleOverriddenDescriptors);
|
||||
}
|
||||
|
||||
// Check if everything that must be overridden, actually is
|
||||
@@ -271,34 +281,6 @@ public class OverrideResolver {
|
||||
trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor));
|
||||
break;
|
||||
}
|
||||
|
||||
// Set<FunctionDescriptor> allOverriddenFunctions = Sets.newHashSet();
|
||||
// Collection<DeclarationDescriptor> allDescriptors = classDescriptor.getDefaultType().getMemberScope().getAllDescriptors();
|
||||
// for (DeclarationDescriptor descriptor : allDescriptors) {
|
||||
// if (descriptor instanceof FunctionDescriptor) {
|
||||
// FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||
// if (functionDescriptor.getModality() != Modality.ABSTRACT) {
|
||||
// for (FunctionDescriptor overriddenDescriptor : functionDescriptor.getOverriddenDescriptors()) {
|
||||
// allOverriddenFunctions.add(overriddenDescriptor.getOriginal());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// boolean foundError = false;
|
||||
// for (DeclarationDescriptor descriptor : allDescriptors) {
|
||||
// if (descriptor instanceof FunctionDescriptor) {
|
||||
// FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||
// if (functionDescriptor.getModality() == Modality.ABSTRACT && !allOverriddenFunctions.contains(functionDescriptor.getOriginal()) && !foundError && nameIdentifier != null) {
|
||||
// DeclarationDescriptor declarationDescriptor = functionDescriptor.getContainingDeclaration();
|
||||
// if (declarationDescriptor != classDescriptor) {
|
||||
//// trace.getErrorHandler().genericError(nameIdentifier.getNode(), "Class '" + klass.getName() + "' must be declared abstract or implement abstract method '" +
|
||||
//// functionDescriptor.getName() + "' declared in " + declarationDescriptor.getName());
|
||||
// trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, functionDescriptor));
|
||||
// foundError = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
public static void collectMissingImplementations(MutableClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl) {
|
||||
@@ -317,21 +299,21 @@ public class OverrideResolver {
|
||||
}
|
||||
}
|
||||
else {
|
||||
Collection<CallableMemberDescriptor> overridenDeclarations = OverridingUtil.getOverridenDeclarations(descriptor);
|
||||
if (overridenDeclarations.size() == 0) {
|
||||
Collection<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverridenDeclarations(descriptor);
|
||||
if (overriddenDeclarations.size() == 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
else if (overridenDeclarations.size() == 1) {
|
||||
CallableMemberDescriptor single = overridenDeclarations.iterator().next();
|
||||
else if (overriddenDeclarations.size() == 1) {
|
||||
CallableMemberDescriptor single = overriddenDeclarations.iterator().next();
|
||||
if (single.getModality() == Modality.ABSTRACT) {
|
||||
abstractNoImpl.add(single);
|
||||
}
|
||||
}
|
||||
else {
|
||||
List<CallableMemberDescriptor> nonAbstractManyImpl = Lists.newArrayList();
|
||||
for (CallableMemberDescriptor overriden : overridenDeclarations) {
|
||||
if (overriden.getModality() != Modality.ABSTRACT) {
|
||||
nonAbstractManyImpl.add(overriden);
|
||||
for (CallableMemberDescriptor overridden : overriddenDeclarations) {
|
||||
if (overridden.getModality() != Modality.ABSTRACT) {
|
||||
nonAbstractManyImpl.add(overridden);
|
||||
}
|
||||
}
|
||||
if (nonAbstractManyImpl.size() > 1) {
|
||||
@@ -371,7 +353,8 @@ public class OverrideResolver {
|
||||
return factoredMembers;
|
||||
}
|
||||
|
||||
private void checkOverride(CallableMemberDescriptor declared) {
|
||||
private void checkOverrideForMember(@NotNull CallableMemberDescriptor declared,
|
||||
@NotNull Multimap<CallableDescriptor, CallableDescriptor> invisibleOverriddenDescriptors) {
|
||||
JetNamedDeclaration member = (JetNamedDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
|
||||
if (member == null) {
|
||||
assert trace.get(DELEGATED, declared);
|
||||
@@ -410,7 +393,13 @@ public class OverrideResolver {
|
||||
}
|
||||
}
|
||||
if (hasOverrideModifier && declared.getOverriddenDescriptors().size() == 0) {
|
||||
trace.report(NOTHING_TO_OVERRIDE.on(member, declared));
|
||||
if (!invisibleOverriddenDescriptors.get(declared).isEmpty()) {
|
||||
CallableDescriptor descriptor = invisibleOverriddenDescriptors.values().iterator().next();
|
||||
trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, descriptor, descriptor.getContainingDeclaration()));
|
||||
}
|
||||
else {
|
||||
trace.report(NOTHING_TO_OVERRIDE.on(member, declared));
|
||||
}
|
||||
}
|
||||
PsiElement nameIdentifier = member.getNameIdentifier();
|
||||
if (!hasOverrideModifier && declared.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) {
|
||||
@@ -427,38 +416,102 @@ public class OverrideResolver {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkVisibilityForOverriddenMembers() {
|
||||
for (Map.Entry<JetNamedFunction, SimpleFunctionDescriptor> entry : context.getFunctions().entrySet()) {
|
||||
JetNamedFunction function = entry.getKey();
|
||||
SimpleFunctionDescriptor functionDescriptor = entry.getValue();
|
||||
|
||||
checkVisibilityForMember(functionDescriptor.getVisibility(), function, functionDescriptor.getOverriddenDescriptors());
|
||||
private void resolveUnknownVisibilityForMembers(@NotNull Set<CallableMemberDescriptor> fakeOverrides) {
|
||||
for (CallableMemberDescriptor override : fakeOverrides) {
|
||||
resolveUnknownVisibilityForMember(override);
|
||||
}
|
||||
for (Map.Entry<JetProperty, PropertyDescriptor> entry : context.getProperties().entrySet()) {
|
||||
JetProperty property = entry.getKey();
|
||||
PropertyDescriptor propertyDescriptor = entry.getValue();
|
||||
|
||||
checkVisibilityForMember(propertyDescriptor.getVisibility(), property, propertyDescriptor.getOverriddenDescriptors());
|
||||
for (CallableMemberDescriptor memberDescriptor : context.getMembers().values()) {
|
||||
resolveUnknownVisibilityForMember(memberDescriptor);
|
||||
}
|
||||
for (PropertyDescriptor propertyDescriptor : context.getPrimaryConstructorParameterProperties()) {
|
||||
PsiElement parameter = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), propertyDescriptor);
|
||||
if (parameter instanceof JetParameter) {
|
||||
checkVisibilityForMember(propertyDescriptor.getVisibility(), (JetParameter)parameter, propertyDescriptor.getOverriddenDescriptors());
|
||||
for (PropertyDescriptor propertyDescriptor : context.getProperties().values()) {
|
||||
for (PropertyAccessorDescriptor accessor : propertyDescriptor.getAccessors()) {
|
||||
if (accessor != null && accessor.getVisibility() == Visibilities.INHERITED) {
|
||||
accessor.setVisibility(propertyDescriptor.getVisibility());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkVisibilityForMember(@NotNull Visibility visibility,
|
||||
@NotNull JetModifierListOwner modifierListOwner,
|
||||
@NotNull Collection<? extends CallableMemberDescriptor> descriptors) {
|
||||
private void resolveUnknownVisibilityForMember(@NotNull CallableMemberDescriptor memberDescriptor) {
|
||||
resolveUnknownVisibilityForOverriddenDescriptors(memberDescriptor.getOverriddenDescriptors());
|
||||
if (memberDescriptor.getVisibility() != Visibilities.INHERITED) {
|
||||
return;
|
||||
}
|
||||
|
||||
Visibility visibility = findMaxVisibility(memberDescriptor.getOverriddenDescriptors());
|
||||
|
||||
if (memberDescriptor instanceof PropertyDescriptor) {
|
||||
((PropertyDescriptor)memberDescriptor).setVisibility(visibility);
|
||||
}
|
||||
else {
|
||||
assert memberDescriptor instanceof FunctionDescriptorImpl;
|
||||
((FunctionDescriptorImpl)memberDescriptor).setVisibility(visibility);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeInvisibleOverriddenDescriptors(@NotNull Multimap<CallableDescriptor, CallableDescriptor> invisibleOverriddenDescriptors) {
|
||||
for (CallableMemberDescriptor memberDescriptor : context.getMembers().values()) {
|
||||
Set<? extends CallableDescriptor> overriddenDescriptors = memberDescriptor.getOverriddenDescriptors();
|
||||
for (Iterator<? extends CallableDescriptor> iterator = overriddenDescriptors.iterator(); iterator.hasNext(); ) {
|
||||
CallableDescriptor superDescriptor = iterator.next();
|
||||
if (!Visibilities.isVisible(superDescriptor, memberDescriptor)) {
|
||||
invisibleOverriddenDescriptors.put(memberDescriptor, superDescriptor);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveUnknownVisibilityForOverriddenDescriptors(@NotNull Collection<? extends CallableMemberDescriptor> descriptors) {
|
||||
for (CallableMemberDescriptor descriptor : descriptors) {
|
||||
if (descriptor.getVisibility() == Visibilities.INHERITED) {
|
||||
resolveUnknownVisibilityForMember(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Visibility findMaxVisibility(@NotNull Collection<? extends CallableMemberDescriptor> descriptors) {
|
||||
if (descriptors.isEmpty()) {
|
||||
return Visibilities.INTERNAL;
|
||||
}
|
||||
Visibility maxVisibility = null;
|
||||
for (CallableMemberDescriptor descriptor : descriptors) {
|
||||
Visibility visibility = descriptor.getVisibility();
|
||||
assert visibility != Visibilities.INHERITED;
|
||||
if (maxVisibility == null) {
|
||||
maxVisibility = visibility;
|
||||
continue;
|
||||
}
|
||||
Integer compare = Visibilities.compare(visibility, maxVisibility);
|
||||
if (compare == null) {
|
||||
maxVisibility = Visibilities.PUBLIC; //todo error or warning when inference only from incomparable visibilities
|
||||
continue;
|
||||
}
|
||||
if (compare > 0) {
|
||||
maxVisibility = visibility;
|
||||
}
|
||||
}
|
||||
assert maxVisibility != null;
|
||||
return maxVisibility;
|
||||
}
|
||||
|
||||
private void checkVisibility() {
|
||||
for (Map.Entry<JetDeclaration, CallableMemberDescriptor> entry : context.getMembers().entrySet()) {
|
||||
checkVisibilityForMember(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void checkVisibilityForMember(@NotNull JetDeclaration declaration, @NotNull CallableMemberDescriptor memberDescriptor) {
|
||||
Visibility visibility = memberDescriptor.getVisibility();
|
||||
for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
|
||||
Integer compare = Visibilities.compare(visibility, descriptor.getVisibility());
|
||||
if (compare == null) {
|
||||
trace.report(CANNOT_CHANGE_ACCESS_PRIVILEGE.on(modifierListOwner, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
|
||||
trace.report(CANNOT_CHANGE_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
|
||||
return;
|
||||
}
|
||||
if (compare < 0) {
|
||||
trace.report(CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(modifierListOwner, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
|
||||
else if (compare < 0) {
|
||||
trace.report(CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -46,7 +47,8 @@ public class TopDownAnalysisContext {
|
||||
private final Map<JetNamedFunction, SimpleFunctionDescriptor> functions = Maps.newLinkedHashMap();
|
||||
private final Map<JetSecondaryConstructor, ConstructorDescriptor> constructors = Maps.newLinkedHashMap();
|
||||
private final Map<JetProperty, PropertyDescriptor> properties = Maps.newLinkedHashMap();
|
||||
private final Set<PropertyDescriptor> primaryConstructorParameterProperties = Sets.newHashSet();
|
||||
private final Map<JetParameter, PropertyDescriptor> primaryConstructorParameterProperties = Maps.newHashMap();
|
||||
private Map<JetDeclaration, CallableMemberDescriptor> members = null;
|
||||
|
||||
private StringBuilder debugOutput;
|
||||
|
||||
@@ -114,7 +116,7 @@ public class TopDownAnalysisContext {
|
||||
return namespaceDescriptors;
|
||||
}
|
||||
|
||||
public Set<PropertyDescriptor> getPrimaryConstructorParameterProperties() {
|
||||
public Map<JetParameter, PropertyDescriptor> getPrimaryConstructorParameterProperties() {
|
||||
return primaryConstructorParameterProperties;
|
||||
}
|
||||
|
||||
@@ -134,4 +136,13 @@ public class TopDownAnalysisContext {
|
||||
return functions;
|
||||
}
|
||||
|
||||
public Map<JetDeclaration, CallableMemberDescriptor> getMembers() {
|
||||
if (members == null) {
|
||||
members = Maps.newHashMap();
|
||||
members.putAll(functions);
|
||||
members.putAll(properties);
|
||||
members.putAll(primaryConstructorParameterProperties);
|
||||
}
|
||||
return members;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,7 +495,9 @@ public class CallResolver {
|
||||
// and throw the results away
|
||||
// We'll type check the arguments later, with the inferred types expected
|
||||
TemporaryBindingTrace traceForUnknown = TemporaryBindingTrace.create(context.trace);
|
||||
JetType type = expressionTypingServices.getType(context.scope, valueArgument.getArgumentExpression(), substituteDontCare.substitute(valueParameterDescriptor.getType(), Variance.INVARIANT), traceForUnknown);
|
||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
JetType type = argumentExpression != null ? expressionTypingServices.getType(context.scope, argumentExpression,
|
||||
substituteDontCare.substitute(valueParameterDescriptor.getType(), Variance.INVARIANT), traceForUnknown) : null;
|
||||
if (type != null && !ErrorUtils.isErrorType(type)) {
|
||||
constraintSystem.addSubtypingConstraint(VALUE_ARGUMENT.assertSubtyping(type, effectiveExpectedType));
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class DataFlowUtils {
|
||||
@NotNull
|
||||
public static DataFlowInfo extractDataFlowInfoFromCondition(@Nullable JetExpression condition, final boolean conditionValue, @Nullable final WritableScope scopeToExtend, final ExpressionTypingContext context) {
|
||||
if (condition == null) return context.dataFlowInfo;
|
||||
final Ref<DataFlowInfo> result = new Ref<DataFlowInfo>(context.dataFlowInfo);
|
||||
final Ref<DataFlowInfo> result = new Ref<DataFlowInfo>(null);
|
||||
condition.accept(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitIsExpression(JetIsExpression expression) {
|
||||
@@ -148,7 +148,7 @@ public class DataFlowUtils {
|
||||
if (result.get() == null) {
|
||||
return context.dataFlowInfo;
|
||||
}
|
||||
return result.get();
|
||||
return context.dataFlowInfo.and(result.get());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -2,7 +2,7 @@ class C() {
|
||||
fun getInstance(): Runnable = C
|
||||
|
||||
class object: Runnable {
|
||||
public override fun run(): Unit { }
|
||||
override fun run(): Unit { }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
fun box() : String {
|
||||
if (!B().test()) return "fail 1";
|
||||
if (!D().test()) return "fail 2"
|
||||
if (!F().test()) return "fail 3"
|
||||
if (!L().test()) return "fail 4"
|
||||
if (!N().test()) return "fail 5"
|
||||
if (!H().test()) return "fail 5"
|
||||
if (!N().test()) return "fail 6"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -31,16 +33,26 @@ class D {
|
||||
fun test() = C().bar() == 1
|
||||
}
|
||||
|
||||
class E
|
||||
fun E.foo() = 2
|
||||
|
||||
class M
|
||||
fun M.foo() = 2
|
||||
class F {
|
||||
fun foo() = 1
|
||||
|
||||
class N {
|
||||
fun M.foo() = 1
|
||||
fun E.bar() = foo()
|
||||
|
||||
fun M.bar() = foo()
|
||||
fun test() = E().bar() == 1
|
||||
}
|
||||
|
||||
fun test() = M().bar() == 1
|
||||
class G
|
||||
fun G.foo() = 2
|
||||
|
||||
class H {
|
||||
fun G.foo() = 1
|
||||
|
||||
fun G.bar() = foo()
|
||||
|
||||
fun test() = G().bar() == 1
|
||||
}
|
||||
|
||||
class K
|
||||
@@ -51,3 +63,13 @@ class L {
|
||||
}
|
||||
fun K.foo() = 1
|
||||
fun L.foo() = 2
|
||||
|
||||
class M
|
||||
class N {
|
||||
fun foo() = 1
|
||||
fun M.foo() = 2
|
||||
|
||||
fun M.bar() = foo()
|
||||
|
||||
fun test() = M().bar() == 1
|
||||
}
|
||||
|
||||
@@ -78,25 +78,25 @@ fun box() : String {
|
||||
}
|
||||
|
||||
class MyCollection1(): java.lang.Iterable<Int> {
|
||||
public override fun iterator(): java.util.Iterator<Int> = MyIterator()
|
||||
override fun iterator(): java.util.Iterator<Int> = MyIterator()
|
||||
|
||||
class MyIterator(): java.util.Iterator<Int> {
|
||||
var k : Int = 5
|
||||
|
||||
public override fun next() : Int = k--
|
||||
public override fun hasNext() = k > 0
|
||||
public override fun remove() {}
|
||||
override fun next() : Int = k--
|
||||
override fun hasNext() = k > 0
|
||||
override fun remove() {}
|
||||
}
|
||||
}
|
||||
|
||||
class MyCollection2(): Iterable<Int> {
|
||||
public override fun iterator(): Iterator<Int> = MyIterator()
|
||||
override fun iterator(): Iterator<Int> = MyIterator()
|
||||
|
||||
class MyIterator(): Iterator<Int> {
|
||||
var k : Int = 5
|
||||
|
||||
public override fun next() : Int = k--
|
||||
public override val hasNext : Boolean
|
||||
override fun next() : Int = k--
|
||||
override val hasNext : Boolean
|
||||
get() = k > 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import java.util.concurrent.atomic.*
|
||||
|
||||
fun thread(block: ()->Unit ) {
|
||||
val thread = object: Thread() {
|
||||
public override fun run() {
|
||||
override fun run() {
|
||||
block()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class C(x: Int, val y : Int) {
|
||||
fun initChild(var x: Int) : java.lang.Object {
|
||||
return object : java.lang.Object() {
|
||||
public override fun toString(): String? {
|
||||
override fun toString(): String? {
|
||||
x = x + y
|
||||
return "child" + x
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package p
|
||||
class C(val y : Int) {
|
||||
val initChild = { ->
|
||||
object : java.lang.Object() {
|
||||
public override fun toString(): String {
|
||||
override fun toString(): String {
|
||||
return "child" + y
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import java.util.ArrayList
|
||||
|
||||
public object SomeObject {
|
||||
private val workerThread = object : Thread() {
|
||||
public override fun run() {
|
||||
override fun run() {
|
||||
foo()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ public object SomeClass {
|
||||
var bug: Any = ""
|
||||
|
||||
private val workerThread = object : Thread() {
|
||||
public override fun run() {
|
||||
override fun run() {
|
||||
try {
|
||||
foo()
|
||||
bug = "none"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
public object RefreshQueue {
|
||||
private val workerThread: Thread = Thread(object : Runnable {
|
||||
public override fun run() {
|
||||
override fun run() {
|
||||
workerThread.isInterrupted()
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,9 +7,9 @@ public abstract class BaseClass() {
|
||||
}
|
||||
|
||||
public class Subclass : BaseClass() {
|
||||
protected override val kind : String = "Physical"
|
||||
override val kind : String = "Physical"
|
||||
|
||||
protected override val kind2 : String = " kind2"
|
||||
override val kind2 : String = " kind2"
|
||||
}
|
||||
|
||||
fun box():String = if(Subclass().debug() == "Physical kind2") "OK" else "fail"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class MyRange1() : Range<Int> {
|
||||
public override fun contains(item: Int) = true
|
||||
override fun contains(item: Int) = true
|
||||
}
|
||||
|
||||
class MyRange2() {
|
||||
|
||||
@@ -163,7 +163,7 @@ fun t11(var x: Int) : Int {
|
||||
fun t12(x: Int) : Int {
|
||||
var y = x
|
||||
val runnable = object : Runnable {
|
||||
public override fun run () {
|
||||
override fun run () {
|
||||
y = y + 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,11 +95,11 @@ fun LinkedList<Int>.sum(f : (Int, Int) -> Int) : Int {
|
||||
}
|
||||
|
||||
fun <T> List<T>.backwards() : Iterable<T> = object : Iterable<T> {
|
||||
public override fun iterator() : jet.Iterator<T> =
|
||||
override fun iterator() : jet.Iterator<T> =
|
||||
object : jet.Iterator<T> {
|
||||
var current = size()
|
||||
public override fun next() : T = get(--current)
|
||||
public override val hasNext : Boolean get() = current > 0
|
||||
override fun next() : T = get(--current)
|
||||
override val hasNext : Boolean get() = current > 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Book(val name: String) : Comparable<Book> {
|
||||
public override fun compareTo(other: Book) = name.compareTo(other.name)
|
||||
override fun compareTo(other: Book) = name.compareTo(other.name)
|
||||
}
|
||||
|
||||
fun box() = if(Book("239").compareTo(Book("932")) != 0) "OK" else "fail"
|
||||
@@ -3,13 +3,13 @@ import java.util.*
|
||||
fun box() : String {
|
||||
val w = object : Comparator<String?> {
|
||||
|
||||
public override fun compare(o1 : String?, o2 : String?) : Int {
|
||||
override fun compare(o1 : String?, o2 : String?) : Int {
|
||||
val l1 : Int = o1?.length ?: 0
|
||||
val l2 = o2?.length ?: 0
|
||||
return l1 - l2
|
||||
}
|
||||
|
||||
public override fun equals(obj: Any?): Boolean = obj === this
|
||||
override fun equals(obj: Any?): Boolean = obj === this
|
||||
}
|
||||
|
||||
w.compare("aaa", "bbb")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import java.util.ArrayList
|
||||
|
||||
class N() : ArrayList<Any>() {
|
||||
public override fun add(el: Any) : Boolean {
|
||||
override fun add(el: Any) : Boolean {
|
||||
if (!super<ArrayList>.add(el)) {
|
||||
throw Exception()
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ trait SimpleClass : java.lang.Object {
|
||||
}
|
||||
|
||||
class SimpleClassImpl() : SimpleClass {
|
||||
public override fun toString() = "SimpleClassImpl"
|
||||
override fun toString() = "SimpleClassImpl"
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
|
||||
@@ -3,7 +3,7 @@ trait ISized {
|
||||
}
|
||||
|
||||
trait javaUtilIterator<T> : java.util.Iterator<T> {
|
||||
public override fun remove() : Unit {
|
||||
override fun remove() : Unit {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,9 @@ trait javaUtilIterator<T> : java.util.Iterator<T> {
|
||||
class MyIterator<T>(val array : ReadOnlyArray<T>) : javaUtilIterator<T> {
|
||||
private var index = 0
|
||||
|
||||
public override fun hasNext() : Boolean = index < array.size
|
||||
override fun hasNext() : Boolean = index < array.size
|
||||
|
||||
public override fun next() : T = array.get(index++)
|
||||
override fun next() : T = array.get(index++)
|
||||
}
|
||||
|
||||
trait ReadOnlyArray<out T> : ISized, java.lang.Iterable<T> {
|
||||
@@ -23,7 +23,7 @@ trait ReadOnlyArray<out T> : ISized, java.lang.Iterable<T> {
|
||||
fun check(v: Any) = v is T
|
||||
}
|
||||
|
||||
public override fun iterator() : java.util.Iterator<T> = MyIterator<T>(this)
|
||||
override fun iterator() : java.util.Iterator<T> = MyIterator<T>(this)
|
||||
}
|
||||
|
||||
trait WriteOnlyArray<in T> : ISized {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
class X {
|
||||
val <!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>x<!> : Int
|
||||
}
|
||||
@@ -18,12 +17,12 @@ class Z : Y() {
|
||||
|
||||
class MyIterable<T> : Iterable<T>
|
||||
{
|
||||
public override fun iterator(): Iterator<T> = MyIterator()
|
||||
override fun iterator(): Iterator<T> = MyIterator()
|
||||
|
||||
class MyIterator : Iterator<T>
|
||||
{
|
||||
public override val hasNext: Boolean = false
|
||||
public override fun next(): T {
|
||||
override val hasNext: Boolean = false
|
||||
override fun next(): T {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import java.util.Enumeration
|
||||
|
||||
inline fun <T> java.util.Enumeration<T>.iterator() = object: Iterator<T> {
|
||||
public override val hasNext: Boolean
|
||||
override val hasNext: Boolean
|
||||
get() = hasMoreElements()
|
||||
|
||||
public override fun next() = nextElement()
|
||||
override fun next() = nextElement()
|
||||
}
|
||||
|
||||
fun <T : Any> T?.iterator() = object {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
//EA-35646
|
||||
package a
|
||||
|
||||
class MyClass1 {
|
||||
public fun plus() {}
|
||||
}
|
||||
|
||||
fun main(arg: MyClass1) {
|
||||
arg<!TOO_MANY_ARGUMENTS!>+<!><!SYNTAX!><!>
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
//KT-1778 Automatically cast error
|
||||
package kt1778
|
||||
|
||||
fun main(args : Array<String>) {
|
||||
val x = args[0]: Any
|
||||
if(x is java.lang.CharSequence) {
|
||||
if ("a" == x) x.length() else x.length() // OK
|
||||
if ("a" == x || "b" == x) x.length() else x.length() // <– THEN ERROR
|
||||
if ("a" == x && "a" == x) x.length() else x.length() // <– ELSE ERROR
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
//KT-1820 Write test for ASSIGN_OPERATOR_AMBIGUITY
|
||||
package kt1820
|
||||
|
||||
class MyInt(val i: Int) {
|
||||
fun plus(m: MyInt) : MyInt = MyInt(m.i + i)
|
||||
}
|
||||
|
||||
fun Any.plusAssign(<!UNUSED_PARAMETER!>a<!>: Any) {}
|
||||
|
||||
fun test(m: MyInt) {
|
||||
m <!ASSIGN_OPERATOR_AMBIGUITY!>+=<!> m
|
||||
|
||||
var i = 1
|
||||
i <!ASSIGN_OPERATOR_AMBIGUITY!>+=<!> 34
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
//KT-1821 Write test for ITERATOR_AMBIGUITY diagnostic
|
||||
|
||||
trait MyCollectionInterface {
|
||||
}
|
||||
|
||||
trait MyAnotherCollectionInterface {
|
||||
}
|
||||
|
||||
class MyCollection : MyCollectionInterface, MyAnotherCollectionInterface {
|
||||
}
|
||||
|
||||
fun MyCollectionInterface.iterator() = MyIterator()
|
||||
|
||||
fun MyAnotherCollectionInterface.iterator() = MyIterator()
|
||||
|
||||
class MyIterator {
|
||||
fun next() : MyElement = MyElement()
|
||||
fun hasNext() = true
|
||||
}
|
||||
|
||||
class MyElement
|
||||
|
||||
fun test1(collection: MyCollection) {
|
||||
collection.<!OVERLOAD_RESOLUTION_AMBIGUITY!>iterator()<!>
|
||||
for (val element in <!ITERATOR_AMBIGUITY!>collection<!>) {
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ class Test() : Thread("Test") {
|
||||
|
||||
}
|
||||
}
|
||||
public override fun run() {
|
||||
override fun run() {
|
||||
init2() // unresolved
|
||||
Test.init2() // ok
|
||||
}
|
||||
|
||||
+8
-4
@@ -18,7 +18,7 @@ open class D {
|
||||
}
|
||||
|
||||
class E : D() {
|
||||
internal <!NOTHING_TO_OVERRIDE!>override<!> fun self() = this
|
||||
internal <!CANNOT_OVERRIDE_INVISIBLE_MEMBER!>override<!> fun self() = this
|
||||
|
||||
fun test() {
|
||||
val <!UNUSED_VARIABLE!>s<!> : E = self()
|
||||
@@ -31,7 +31,11 @@ open class F {
|
||||
}
|
||||
|
||||
class G : F() {
|
||||
<!CANNOT_CHANGE_ACCESS_PRIVILEGE!>override<!> fun protected_fun() {}
|
||||
override fun protected_fun() {}
|
||||
}
|
||||
|
||||
fun test_fun_stays_protected(g: G) {
|
||||
g.<!INVISIBLE_MEMBER!>protected_fun<!>()
|
||||
}
|
||||
|
||||
//------------
|
||||
@@ -57,11 +61,11 @@ trait T {
|
||||
}
|
||||
|
||||
open class L : T {
|
||||
<!CANNOT_WEAKEN_ACCESS_PRIVILEGE!>override<!> fun foo() {}
|
||||
override fun foo() {}
|
||||
}
|
||||
|
||||
class M : L() {
|
||||
internal override fun foo() {}
|
||||
<!CANNOT_WEAKEN_ACCESS_PRIVILEGE!>internal<!> override fun foo() {}
|
||||
}
|
||||
//---------------
|
||||
trait R {
|
||||
@@ -0,0 +1,40 @@
|
||||
//KT-151 Inherit visibility when overriding
|
||||
package kt151
|
||||
|
||||
open class A {
|
||||
protected open fun x() {}
|
||||
}
|
||||
|
||||
class B : A() {
|
||||
override fun x() {} // No visibility modifier required
|
||||
}
|
||||
|
||||
fun test(b: B) {
|
||||
b.<!INVISIBLE_MEMBER!>x<!>()
|
||||
}
|
||||
|
||||
|
||||
//more tests
|
||||
open class C {
|
||||
internal open fun foo() {}
|
||||
}
|
||||
|
||||
trait T {
|
||||
protected fun foo() {}
|
||||
}
|
||||
|
||||
class D : C(), T {
|
||||
<!CANNOT_CHANGE_ACCESS_PRIVILEGE!>protected<!> override fun foo() {}
|
||||
}
|
||||
|
||||
class E : C(), T {
|
||||
<!CANNOT_CHANGE_ACCESS_PRIVILEGE!>internal<!> override fun foo() {}
|
||||
}
|
||||
|
||||
class F : C(), T {
|
||||
<!CANNOT_WEAKEN_ACCESS_PRIVILEGE!>private<!> override fun foo() {}
|
||||
}
|
||||
|
||||
class G : C(), T {
|
||||
override fun foo() {}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package kt1805
|
||||
//KT-1805 Better diagnostic for access to private field of parent class
|
||||
|
||||
open class Some {
|
||||
private val privateField = 12
|
||||
}
|
||||
|
||||
class SomeSubclass : Some() {
|
||||
fun test() {
|
||||
this.<!INVISIBLE_MEMBER!>privateField<!> // 1. Unresolved reference
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val s2 = Some()
|
||||
s2.<!INVISIBLE_MEMBER!>privateField<!> // 2. Can't access to 'privateField' in Some
|
||||
|
||||
val s1 = SomeSubclass()
|
||||
s1.<!INVISIBLE_MEMBER!>privateField<!> // 3. Unresolved reference
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
//KT-1806 accessing private member in object class/anonymous object is not highlighted as error
|
||||
package kt1806
|
||||
|
||||
object MyObject {
|
||||
private var message: String = "'Static'"
|
||||
|
||||
}
|
||||
|
||||
fun test1() {
|
||||
|
||||
doSmth(MyObject.<!INVISIBLE_MEMBER!>message<!>)
|
||||
}
|
||||
|
||||
val MyObject1 = object {
|
||||
private var message: String = "'Static'"
|
||||
}
|
||||
|
||||
fun test2() {
|
||||
doSmth(MyObject1.<!INVISIBLE_MEMBER!>message<!>)
|
||||
}
|
||||
|
||||
fun doSmth(s: String) = s
|
||||
@@ -12,7 +12,4 @@ class SomeSubclass : Some() {
|
||||
}
|
||||
|
||||
// TIME: 2
|
||||
// EXIST: testPublic, testProtected, testPackage
|
||||
|
||||
// Should exist after KT-1805 Better diagnostic for access to private field of parent class
|
||||
// ABSENT: testPrivate
|
||||
// EXIST: testPublic, testProtected, testPackage, testPrivate
|
||||
|
||||
@@ -4,5 +4,5 @@ open class A {
|
||||
}
|
||||
|
||||
class B : A() {
|
||||
<caret>override fun run() {}
|
||||
<caret>internal override fun run() {}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ trait ParseResult<out T> {
|
||||
public val value : T
|
||||
}
|
||||
|
||||
class Success<T>(<caret>override val value : T) : ParseResult<T> {
|
||||
class Success<T>(<caret>internal override val value : T) : ParseResult<T> {
|
||||
public override val success : Boolean = true
|
||||
}
|
||||
@@ -4,23 +4,23 @@ import kotlin.test.Asserter
|
||||
import org.junit.Assert
|
||||
|
||||
class JUnitAsserter : Asserter {
|
||||
public override fun assertEquals(message : String, expected : Any?, actual : Any?) {
|
||||
override fun assertEquals(message : String, expected : Any?, actual : Any?) {
|
||||
Assert.assertEquals(message, expected, actual)
|
||||
}
|
||||
|
||||
public override fun assertNotNull(message : String, actual : Any?) {
|
||||
override fun assertNotNull(message : String, actual : Any?) {
|
||||
Assert.assertNotNull(message, actual)
|
||||
}
|
||||
|
||||
public override fun assertNull(message : String, actual : Any?) {
|
||||
override fun assertNull(message : String, actual : Any?) {
|
||||
Assert.assertNull(message, actual)
|
||||
}
|
||||
|
||||
public override fun assertTrue(message : String, actual : Boolean) {
|
||||
override fun assertTrue(message : String, actual : Boolean) {
|
||||
Assert.assertTrue(message, actual)
|
||||
}
|
||||
|
||||
public override fun fail(message : String) {
|
||||
override fun fail(message : String) {
|
||||
Assert.fail(message)
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public inline fun <T> java.util.Iterator<T>.iterator() : java.util.Iterator<T> =
|
||||
Helper to make java.util.Enumeration usable in for
|
||||
*/
|
||||
public fun <erased T> java.util.Enumeration<T>.iterator(): Iterator<T> = object: Iterator<T> {
|
||||
public override val hasNext: Boolean
|
||||
override val hasNext: Boolean
|
||||
get() = hasMoreElements()
|
||||
|
||||
public override fun next() : T = nextElement().sure()
|
||||
@@ -114,4 +114,4 @@ public inline fun Throwable.printStackTrace(writer: PrintWriter): Unit {
|
||||
public inline fun Throwable.printStackTrace(stream: PrintStream): Unit {
|
||||
val jlt = this as java.lang.Throwable
|
||||
jlt.printStackTrace(stream)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,15 +35,15 @@ abstract class FunctionalList<T>(public val size: Int) {
|
||||
return head
|
||||
}
|
||||
|
||||
public override val hasNext: Boolean
|
||||
override val hasNext: Boolean
|
||||
get() = !cur.empty
|
||||
}
|
||||
|
||||
class object {
|
||||
class Empty<T>() : FunctionalList<T>(0) {
|
||||
public override val head: T
|
||||
override val head: T
|
||||
get() = throw java.util.NoSuchElementException()
|
||||
public override val tail: FunctionalList<T>
|
||||
override val tail: FunctionalList<T>
|
||||
get() = throw java.util.NoSuchElementException()
|
||||
}
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ fun Node.nextSiblings() : Iterator<Node> = NextSiblingIterator(this)
|
||||
|
||||
class NextSiblingIterator(var node: Node) : AbstractIterator<Node>() {
|
||||
|
||||
protected override fun computeNext(): Unit {
|
||||
override fun computeNext(): Unit {
|
||||
val next = node.getNextSibling()
|
||||
if (next != null) {
|
||||
setNext(next)
|
||||
@@ -215,7 +215,7 @@ fun Node.previousSiblings() : Iterator<Node> = PreviousSiblingIterator(this)
|
||||
|
||||
class PreviousSiblingIterator(var node: Node) : AbstractIterator<Node>() {
|
||||
|
||||
protected override fun computeNext(): Unit {
|
||||
override fun computeNext(): Unit {
|
||||
val next = node.getPreviousSibling()
|
||||
if (next != null) {
|
||||
setNext(next)
|
||||
@@ -323,7 +323,7 @@ fun NodeList?.toXmlString(xmlDeclaration: Boolean = false): String {
|
||||
}
|
||||
|
||||
class NodeListAsList(val nodeList: NodeList): AbstractList<Node>() {
|
||||
public override fun get(index: Int): Node {
|
||||
override fun get(index: Int): Node {
|
||||
val node = nodeList.item(index)
|
||||
if (node == null) {
|
||||
throw IndexOutOfBoundsException("NodeList does not contain a node at index: " + index)
|
||||
@@ -332,11 +332,11 @@ class NodeListAsList(val nodeList: NodeList): AbstractList<Node>() {
|
||||
}
|
||||
}
|
||||
|
||||
public override fun size(): Int = nodeList.getLength()
|
||||
override fun size(): Int = nodeList.getLength()
|
||||
}
|
||||
|
||||
class ElementListAsList(val nodeList: NodeList): AbstractList<Element>() {
|
||||
public override fun get(index: Int): Element {
|
||||
override fun get(index: Int): Element {
|
||||
val node = nodeList.item(index)
|
||||
if (node is Element) {
|
||||
return node
|
||||
@@ -349,7 +349,7 @@ class ElementListAsList(val nodeList: NodeList): AbstractList<Element>() {
|
||||
}
|
||||
}
|
||||
|
||||
public override fun size(): Int = nodeList.getLength()
|
||||
override fun size(): Int = nodeList.getLength()
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ public inline fun <T: Closeable, R> T.use(block: (T)-> R) : R {
|
||||
/** Returns an [Iterator] of bytes over an input stream */
|
||||
public fun InputStream.iterator() : ByteIterator =
|
||||
object: ByteIterator() {
|
||||
public override val hasNext : Boolean
|
||||
override val hasNext : Boolean
|
||||
get() = available() > 0
|
||||
|
||||
public override fun nextByte() : Byte = read().toByte()
|
||||
@@ -238,7 +238,7 @@ class LineIterator(val reader: BufferedReader) : Iterator<String> {
|
||||
private var nextValue: String? = null
|
||||
private var done = false
|
||||
|
||||
public override val hasNext: Boolean
|
||||
override val hasNext: Boolean
|
||||
get() {
|
||||
if (nextValue == null && !done) {
|
||||
nextValue = reader.readLine()
|
||||
|
||||
@@ -17,7 +17,7 @@ public abstract class AbstractIterator<T>: java.util.Iterator<T> {
|
||||
private var state: State = State.NotReady
|
||||
private var next: T? = null
|
||||
|
||||
public override fun hasNext(): Boolean {
|
||||
override fun hasNext(): Boolean {
|
||||
require(state != State.Failed)
|
||||
return when (state) {
|
||||
State.Done -> false
|
||||
@@ -26,13 +26,13 @@ public abstract class AbstractIterator<T>: java.util.Iterator<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public override fun next(): T {
|
||||
override fun next(): T {
|
||||
if (!hasNext()) throw NoSuchElementException()
|
||||
state = State.NotReady
|
||||
return next.sure()
|
||||
}
|
||||
|
||||
public override fun remove() {
|
||||
override fun remove() {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
|
||||
@@ -389,7 +389,7 @@ class CollectionTest {
|
||||
class IterableWrapper<T>(collection : java.lang.Iterable<T>) : java.lang.Iterable<T> {
|
||||
private val collection = collection
|
||||
|
||||
public override fun iterator(): java.util.Iterator<T> {
|
||||
override fun iterator(): java.util.Iterator<T> {
|
||||
return collection.iterator().sure()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,10 +43,10 @@ class CompareTest {
|
||||
|
||||
Test fun sortUsingCustomComparator() {
|
||||
val c = object : Comparator<Item>{
|
||||
public override fun compare(o1: Item?, o2: Item?): Int {
|
||||
override fun compare(o1: Item?, o2: Item?): Int {
|
||||
return compareBy(o1, o2, {(it: Item) -> it.name}, {(it: Item) -> it.rating})
|
||||
}
|
||||
public override fun equals(obj: Any?): Boolean {
|
||||
override fun equals(obj: Any?): Boolean {
|
||||
return this == obj
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,13 @@ class TestBuilt<T>(name: String, val builder: TestBuilder<T>, val test: TestBuil
|
||||
get() = myState.sure()
|
||||
set(newState: T) { myState = newState }
|
||||
|
||||
public override fun countTestCases(): Int = 1
|
||||
override fun countTestCases(): Int = 1
|
||||
|
||||
protected override fun setUp() = this.(builder.setUp)()
|
||||
override fun setUp() = this.(builder.setUp)()
|
||||
|
||||
protected override fun tearDown() = this.(builder.tearDown)()
|
||||
override fun tearDown() = this.(builder.tearDown)()
|
||||
|
||||
protected override fun runTest() = this.(test)()
|
||||
override fun runTest() = this.(test)()
|
||||
}
|
||||
|
||||
open class TestBuilder<T>(name: String) {
|
||||
|
||||
@@ -10,7 +10,7 @@ import junit.framework.TestCase
|
||||
import junit.framework.Assert
|
||||
|
||||
class Serial(val a : String) : java.lang.Object(), Serializable {
|
||||
public override fun toString() = a
|
||||
override fun toString() = a
|
||||
}
|
||||
|
||||
class SerialTest() : TestCase() {
|
||||
|
||||
@@ -28,7 +28,7 @@ class Customer() : ChangeSupport() {
|
||||
class MyChangeListener() : ChangeListener {
|
||||
val events = ArrayList<ChangeEvent>()
|
||||
|
||||
public override fun onPropertyChange(event: ChangeEvent): Unit {
|
||||
override fun onPropertyChange(event: ChangeEvent): Unit {
|
||||
println("Property changed: $event")
|
||||
events.add(event)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user