Private setter is now forbidden for non-private late init variables
This commit is contained in:
@@ -322,6 +322,7 @@ public interface Errors {
|
||||
|
||||
DiagnosticFactory0<PsiElement> REDUNDANT_MODIFIER_IN_GETTER = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<PsiElement> GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> PRIVATE_SETTER_ON_NON_PRIVATE_LATE_INIT_VAR = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory2<JetTypeReference, JetType, JetType> WRONG_GETTER_RETURN_TYPE = DiagnosticFactory2.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<JetModifierListOwner>
|
||||
|
||||
+1
@@ -221,6 +221,7 @@ public class DefaultErrorMessages {
|
||||
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(PRIVATE_SETTER_ON_NON_PRIVATE_LATE_INIT_VAR, "Private setter is not allowed on non-private lateinit property");
|
||||
MAP.put(BACKING_FIELD_IN_TRAIT, "Property in an interface cannot have a backing field");
|
||||
MAP.put(MUST_BE_INITIALIZED, "Property must be initialized");
|
||||
MAP.put(MUST_BE_INITIALIZED_OR_BE_ABSTRACT, "Property must be initialized or be abstract");
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken;
|
||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||
@@ -672,22 +673,39 @@ public class DeclarationsChecker {
|
||||
assert propertyAccessorDescriptor != null : "No property accessor descriptor for " + property.getText();
|
||||
modifiersChecker.checkModifiersForDeclaration(accessor, propertyAccessorDescriptor);
|
||||
}
|
||||
JetPropertyAccessor getter = property.getGetter();
|
||||
PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
|
||||
JetModifierList getterModifierList = getter != null ? getter.getModifierList() : null;
|
||||
if (getterModifierList != null && getterDescriptor != null) {
|
||||
Map<JetModifierKeywordToken, PsiElement> tokens = modifiersChecker.getTokensCorrespondingToModifiers(getterModifierList, Sets
|
||||
checkAccessor(propertyDescriptor, property.getGetter(), propertyDescriptor.getGetter());
|
||||
checkAccessor(propertyDescriptor, property.getSetter(), propertyDescriptor.getSetter());
|
||||
}
|
||||
|
||||
private void reportVisibilityModifierDiagnostics(Collection<PsiElement> tokens, DiagnosticFactory0<PsiElement> diagnostic) {
|
||||
for (PsiElement token : tokens) {
|
||||
trace.report(diagnostic.on(token));
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAccessor(
|
||||
@NotNull PropertyDescriptor propertyDescriptor,
|
||||
@Nullable JetPropertyAccessor accessor,
|
||||
@Nullable PropertyAccessorDescriptor accessorDescriptor
|
||||
) {
|
||||
if (accessor == null) return;
|
||||
JetModifierList accessorModifierList = accessor.getModifierList();
|
||||
if (accessorModifierList != null && accessorDescriptor != null) {
|
||||
Map<JetModifierKeywordToken, PsiElement> tokens = modifiersChecker.getTokensCorrespondingToModifiers(accessorModifierList, Sets
|
||||
.newHashSet(JetTokens.PUBLIC_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PRIVATE_KEYWORD,
|
||||
JetTokens.INTERNAL_KEYWORD));
|
||||
if (getterDescriptor.getVisibility() != propertyDescriptor.getVisibility()) {
|
||||
for (PsiElement token : tokens.values()) {
|
||||
trace.report(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.on(token));
|
||||
if (accessor.isGetter()) {
|
||||
if (accessorDescriptor.getVisibility() != propertyDescriptor.getVisibility()) {
|
||||
reportVisibilityModifierDiagnostics(tokens.values(), Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY);
|
||||
}
|
||||
else {
|
||||
reportVisibilityModifierDiagnostics(tokens.values(), Errors.REDUNDANT_MODIFIER_IN_GETTER);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (PsiElement token : tokens.values()) {
|
||||
trace.report(Errors.REDUNDANT_MODIFIER_IN_GETTER.on(token));
|
||||
}
|
||||
else if (accessorDescriptor.getVisibility() == Visibilities.PRIVATE
|
||||
&& propertyDescriptor.getVisibility() != Visibilities.PRIVATE
|
||||
&& propertyDescriptor.isLateInit()) {
|
||||
reportVisibilityModifierDiagnostics(tokens.values(), Errors.PRIVATE_SETTER_ON_NON_PRIVATE_LATE_INIT_VAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ public abstract class A<T: Any, V: String?>(<!INAPPLICABLE_LATEINIT_MODIFIER_PRI
|
||||
|
||||
public lateinit var e: String
|
||||
get
|
||||
private set
|
||||
<!PRIVATE_SETTER_ON_NON_PRIVATE_LATE_INIT_VAR!>private<!> set
|
||||
|
||||
fun a() {
|
||||
<!WRONG_MODIFIER_TARGET!>lateinit<!> var <!UNUSED_VARIABLE!>a<!>: String
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
class My {
|
||||
|
||||
lateinit var x: String
|
||||
<!PRIVATE_SETTER_ON_NON_PRIVATE_LATE_INIT_VAR!>private<!> set
|
||||
|
||||
lateinit var y: String
|
||||
// Ok, non-private setter
|
||||
internal set
|
||||
|
||||
lateinit protected var z: String
|
||||
<!PRIVATE_SETTER_ON_NON_PRIVATE_LATE_INIT_VAR!>private<!> set
|
||||
|
||||
lateinit private var w: String
|
||||
// Ok, private var
|
||||
private set
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
public final class My {
|
||||
public constructor My()
|
||||
private final lateinit var w: kotlin.String
|
||||
public final lateinit var x: kotlin.String
|
||||
public final lateinit var y: kotlin.String
|
||||
protected final lateinit var z: kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -325,6 +325,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("LateInitSetter.kt")
|
||||
public void testLateInitSetter() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/LateInitSetter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("LiteralAsResult.kt")
|
||||
public void testLiteralAsResult() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/LiteralAsResult.kt");
|
||||
|
||||
@@ -116,6 +116,7 @@ public class QuickFixRegistrar : QuickFixContributor {
|
||||
|
||||
val removeModifierFactory = RemoveModifierFix.createRemoveModifierFactory()
|
||||
GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.registerFactory(removeModifierFactory)
|
||||
PRIVATE_SETTER_ON_NON_PRIVATE_LATE_INIT_VAR.registerFactory(removeModifierFactory)
|
||||
REDUNDANT_MODIFIER_IN_GETTER.registerFactory(removeRedundantModifierFactory)
|
||||
WRONG_MODIFIER_TARGET.registerFactory(removeModifierFactory)
|
||||
REDUNDANT_MODIFIER_FOR_TARGET.registerFactory(removeModifierFactory)
|
||||
|
||||
Reference in New Issue
Block a user