Unify 'lateinit' diagnostics

This commit is contained in:
Yan Zhulanow
2015-10-08 20:31:56 +03:00
parent 9699708fb8
commit b42d913bd7
5 changed files with 48 additions and 48 deletions
@@ -360,12 +360,7 @@ public interface Errors {
DiagnosticFactory0<JetSimpleNameExpression> BACKING_FIELD_OLD_SYNTAX = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<JetSimpleNameExpression> BACKING_FIELD_OLD_SYNTAX = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetSimpleNameExpression> BACKING_FIELD_USAGE_FORBIDDEN = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<JetSimpleNameExpression> BACKING_FIELD_USAGE_FORBIDDEN = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_LATEINIT_MODIFIER = DiagnosticFactory0.create(ERROR); DiagnosticFactory1<PsiElement, String> INAPPLICABLE_LATEINIT_MODIFIER = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_LATEINIT_MODIFIER_IMMUTABLE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_LATEINIT_MODIFIER_ABSTRACT_PROPERTY = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_LATEINIT_MODIFIER_PRIMARY_CONSTRUCTOR_PARAMETER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_LATEINIT_MODIFIER_NULLABLE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_LATEINIT_MODIFIER_PRIMITIVE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory2<JetModifierListOwner, String, ClassDescriptor> ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS = DiagnosticFactory2.create(ERROR, ABSTRACT_MODIFIER); DiagnosticFactory2<JetModifierListOwner, String, ClassDescriptor> ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS = DiagnosticFactory2.create(ERROR, ABSTRACT_MODIFIER);
@@ -214,12 +214,7 @@ public class DefaultErrorMessages {
MAP.put(DELEGATED_PROPERTY_IN_INTERFACE, "Delegated properties are not allowed in interfaces"); MAP.put(DELEGATED_PROPERTY_IN_INTERFACE, "Delegated properties are not allowed in interfaces");
MAP.put(LOCAL_VARIABLE_WITH_DELEGATE, "Local variables are not allowed to have delegates"); MAP.put(LOCAL_VARIABLE_WITH_DELEGATE, "Local variables are not allowed to have delegates");
MAP.put(INAPPLICABLE_LATEINIT_MODIFIER, "''lateinit'' modifier is allowed only on member properties with a backing field"); MAP.put(INAPPLICABLE_LATEINIT_MODIFIER, "''lateinit'' modifier {0}", STRING);
MAP.put(INAPPLICABLE_LATEINIT_MODIFIER_IMMUTABLE, "''lateinit'' modifier is allowed only on mutable properties");
MAP.put(INAPPLICABLE_LATEINIT_MODIFIER_ABSTRACT_PROPERTY, "''lateinit'' modifier is not allowed on abstract properties");
MAP.put(INAPPLICABLE_LATEINIT_MODIFIER_PRIMARY_CONSTRUCTOR_PARAMETER, "''lateinit'' modifier is not allowed on primary constructor parameters");
MAP.put(INAPPLICABLE_LATEINIT_MODIFIER_NULLABLE, "''lateinit'' modifier is not allowed on nullable properties");
MAP.put(INAPPLICABLE_LATEINIT_MODIFIER_PRIMITIVE, "''lateinit'' modifier is not allowed on primitive type properties");
MAP.put(GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, "Getter visibility must be the same as property visibility"); MAP.put(GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, "Getter visibility must be the same as property visibility");
MAP.put(PRIVATE_SETTER_ON_NON_PRIVATE_LATE_INIT_VAR, "Private setter is not allowed on non-private lateinit property"); MAP.put(PRIVATE_SETTER_ON_NON_PRIVATE_LATE_INIT_VAR, "Private setter is not allowed on non-private lateinit property");
@@ -514,8 +514,7 @@ public class DeclarationsChecker {
if (modifier == null) return; if (modifier == null) return;
if (!propertyDescriptor.isVar()) { if (!propertyDescriptor.isVar()) {
trace.report(INAPPLICABLE_LATEINIT_MODIFIER_IMMUTABLE.on(modifier)); trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is allowed only on mutable properties"));
return;
} }
boolean returnTypeIsNullable = true; boolean returnTypeIsNullable = true;
@@ -528,32 +527,29 @@ public class DeclarationsChecker {
} }
if (returnTypeIsNullable) { if (returnTypeIsNullable) {
trace.report(INAPPLICABLE_LATEINIT_MODIFIER_NULLABLE.on(modifier)); trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on nullable properties"));
return;
} }
if (returnTypeIsPrimitive) { if (returnTypeIsPrimitive) {
trace.report(INAPPLICABLE_LATEINIT_MODIFIER_PRIMITIVE.on(modifier)); trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on primitive type properties"));
return;
} }
if (propertyDescriptor.getModality() == Modality.ABSTRACT) { boolean isAbstract = propertyDescriptor.getModality() == Modality.ABSTRACT;
trace.report(INAPPLICABLE_LATEINIT_MODIFIER_ABSTRACT_PROPERTY.on(modifier)); if (isAbstract) {
return; trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on abstract properties"));
} }
if (property instanceof JetParameter) { if (property instanceof JetParameter) {
trace.report(INAPPLICABLE_LATEINIT_MODIFIER_PRIMARY_CONSTRUCTOR_PARAMETER.on(modifier)); trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on primary constructor parameters"));
return;
} }
boolean hasBackingField = boolean hasDelegateExpressionOrInitializer = false;
Boolean.TRUE.equals(trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor));
boolean hasDelegateOrInitializer = false;
if (property instanceof JetProperty) { if (property instanceof JetProperty) {
hasDelegateOrInitializer = ((JetProperty) property).hasDelegateExpressionOrInitializer(); hasDelegateExpressionOrInitializer = ((JetProperty) property).hasDelegateExpressionOrInitializer();
if (hasDelegateExpressionOrInitializer) {
trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier,
"is not allowed on properties with initializer or on delegated properties"));
}
} }
PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
@@ -567,9 +563,19 @@ public class DeclarationsChecker {
customGetterOrSetter |= setter.hasBody(); customGetterOrSetter |= setter.hasBody();
} }
if (!hasBackingField || hasDelegateOrInitializer || customGetterOrSetter if (!hasDelegateExpressionOrInitializer && customGetterOrSetter) {
|| propertyDescriptor.getExtensionReceiverParameter() != null) { trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on properties with a custom getter or setter"));
trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier)); }
boolean hasBackingField =
Boolean.TRUE.equals(trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor));
if (!isAbstract && !customGetterOrSetter && !hasDelegateExpressionOrInitializer && !hasBackingField) {
trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on properties without backing field"));
}
if (propertyDescriptor.getExtensionReceiverParameter() != null) {
trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on extension properties"));
} }
} }
+17 -14
View File
@@ -2,15 +2,16 @@ import kotlin.reflect.KProperty
class CustomDelegate { class CustomDelegate {
operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name
operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: String) {}
} }
public abstract class A<T: Any, V: String?>(<!INAPPLICABLE_LATEINIT_MODIFIER_PRIMARY_CONSTRUCTOR_PARAMETER!>lateinit<!> var p2: String) { public abstract class A<T: Any, V: String?>(<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var p2: String) {
public <!INAPPLICABLE_LATEINIT_MODIFIER_IMMUTABLE!>lateinit<!> val a: String public <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val a: String
<!INAPPLICABLE_LATEINIT_MODIFIER_IMMUTABLE!>lateinit<!> val b: T <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val b: T
private lateinit var c: CharSequence private lateinit var c: CharSequence
<!INAPPLICABLE_LATEINIT_MODIFIER_IMMUTABLE!>lateinit<!> val d: String <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val d: String
get get
public lateinit var e: String public lateinit var e: String
@@ -21,33 +22,35 @@ public abstract class A<T: Any, V: String?>(<!INAPPLICABLE_LATEINIT_MODIFIER_PRI
<!WRONG_MODIFIER_TARGET!>lateinit<!> var <!UNUSED_VARIABLE!>a<!>: String <!WRONG_MODIFIER_TARGET!>lateinit<!> var <!UNUSED_VARIABLE!>a<!>: String
} }
<!INAPPLICABLE_LATEINIT_MODIFIER_NULLABLE!>lateinit<!> var e1: V <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e1: V
<!INAPPLICABLE_LATEINIT_MODIFIER_NULLABLE!>lateinit<!> var e2: String? <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e2: String?
<!INAPPLICABLE_LATEINIT_MODIFIER_PRIMITIVE!>lateinit<!> var e3: Int <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e3: Int
<!INAPPLICABLE_LATEINIT_MODIFIER_NULLABLE!>lateinit<!> var e4: Int? <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e4: Int?
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e5 = "A" <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e5 = "A"
<!INAPPLICABLE_LATEINIT_MODIFIER_PRIMITIVE!>lateinit<!> var e6 = 3
<!INAPPLICABLE_LATEINIT_MODIFIER_IMMUTABLE!>lateinit<!> val e7 by CustomDelegate() // With initializer, primitive
<!INAPPLICABLE_LATEINIT_MODIFIER, INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e6 = 3
<!INAPPLICABLE_LATEINIT_MODIFIER_IMMUTABLE!>lateinit<!> val e8: String <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e7 by CustomDelegate()
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e8: String
get() = "A" get() = "A"
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e9: String <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e9: String
set(v) { field = v } set(v) { field = v }
abstract <!INAPPLICABLE_LATEINIT_MODIFIER_ABSTRACT_PROPERTY!>lateinit<!> var e10: String abstract <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e10: String
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var String.e11: String <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var String.e11: String
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var String.e12: String <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var String.e12: String
} }
<!INAPPLICABLE_LATEINIT_MODIFIER_IMMUTABLE, WRONG_MODIFIER_TARGET!>lateinit<!> val topLevel: String <!INAPPLICABLE_LATEINIT_MODIFIER, WRONG_MODIFIER_TARGET!>lateinit<!> val topLevel: String
<!WRONG_MODIFIER_TARGET!>lateinit<!> var topLevelMutable: String <!WRONG_MODIFIER_TARGET!>lateinit<!> var topLevelMutable: String
public interface Intf { public interface Intf {
<!INAPPLICABLE_LATEINIT_MODIFIER_ABSTRACT_PROPERTY!>lateinit<!> var str: String <!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var str: String
} }
public abstract class AbstractClass { public abstract class AbstractClass {
+3 -2
View File
@@ -17,8 +17,8 @@ public abstract class A</*0*/ T : kotlin.Any, /*1*/ V : kotlin.String?> {
public final lateinit var e4: kotlin.Int? public final lateinit var e4: kotlin.Int?
public final lateinit var e5: kotlin.String public final lateinit var e5: kotlin.String
public final lateinit var e6: kotlin.Int public final lateinit var e6: kotlin.Int
public final lateinit val e7: kotlin.String public final lateinit var e7: kotlin.String
public final lateinit val e8: kotlin.String public final lateinit var e8: kotlin.String
public final lateinit var e9: kotlin.String public final lateinit var e9: kotlin.String
public final var p2: kotlin.String public final var p2: kotlin.String
public final lateinit var kotlin.String.e11: kotlin.String public final lateinit var kotlin.String.e11: kotlin.String
@@ -58,6 +58,7 @@ public final class CustomDelegate {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>): kotlin.String public final operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>): kotlin.String
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final operator fun setValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>, /*2*/ value: kotlin.String): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }