Java class with static-only methods can contain 'protected' members (#1257)

#KT-19651 Fixed
This commit is contained in:
Toshiaki Kameyama
2017-09-14 21:47:10 +09:00
committed by Simon Ogorodnik
parent 0f9d31c9d1
commit cd6201c5df
9 changed files with 94 additions and 15 deletions
@@ -83,7 +83,7 @@ class CodeConverter(
val explicitType = type.takeIf { settings.specifyLocalVariableTypeByDefault || converter.shouldDeclareVariableType(variable, type, isVal) } val explicitType = type.takeIf { settings.specifyLocalVariableTypeByDefault || converter.shouldDeclareVariableType(variable, type, isVal) }
return LocalVariable(variable.declarationIdentifier(), return LocalVariable(variable.declarationIdentifier(),
converter.convertAnnotations(variable), converter.convertAnnotations(variable),
converter.convertModifiers(variable, false), converter.convertModifiers(variable, false, false),
explicitType, explicitType,
convertExpression(variable.initializer, variable.type), convertExpression(variable.initializer, variable.type),
isVal).assignPrototype(variable) isVal).assignPrototype(variable)
+18 -8
View File
@@ -162,7 +162,7 @@ class Converter private constructor(
} }
val annotations = convertAnnotations(psiClass) val annotations = convertAnnotations(psiClass)
var modifiers = convertModifiers(psiClass, false) var modifiers = convertModifiers(psiClass, false, false)
val typeParameters = convertTypeParameterList(psiClass.typeParameterList) val typeParameters = convertTypeParameterList(psiClass.typeParameterList)
val extendsTypes = convertToNotNullableTypes(psiClass.extendsList) val extendsTypes = convertToNotNullableTypes(psiClass.extendsList)
val implementsTypes = convertToNotNullableTypes(psiClass.implementsList) val implementsTypes = convertToNotNullableTypes(psiClass.implementsList)
@@ -222,7 +222,7 @@ class Converter private constructor(
settings.openByDefault || referenceSearcher.hasInheritors(psiClass) settings.openByDefault || referenceSearcher.hasInheritors(psiClass)
} }
private fun shouldConvertIntoObject(psiClass: PsiClass): Boolean { fun shouldConvertIntoObject(psiClass: PsiClass): Boolean {
val methods = psiClass.methods val methods = psiClass.methods
val fields = psiClass.fields val fields = psiClass.fields
val classes = psiClass.innerClasses val classes = psiClass.innerClasses
@@ -295,7 +295,7 @@ class Converter private constructor(
return Class(psiClass.declarationIdentifier(), return Class(psiClass.declarationIdentifier(),
convertAnnotations(psiClass), convertAnnotations(psiClass),
convertModifiers(psiClass, false).with(Modifier.ANNOTATION).without(Modifier.ABSTRACT), convertModifiers(psiClass, false, false).with(Modifier.ANNOTATION).without(Modifier.ABSTRACT),
TypeParameterList.Empty, TypeParameterList.Empty,
listOf(), listOf(),
null, null,
@@ -305,7 +305,7 @@ class Converter private constructor(
fun convertInitializer(initializer: PsiClassInitializer): Initializer { fun convertInitializer(initializer: PsiClassInitializer): Initializer {
return Initializer(deferredElement { codeConverter -> codeConverter.convertBlock(initializer.body) }, return Initializer(deferredElement { codeConverter -> codeConverter.convertBlock(initializer.body) },
convertModifiers(initializer, false)).assignPrototype(initializer) convertModifiers(initializer, false, false)).assignPrototype(initializer)
} }
fun convertProperty(propertyInfo: PropertyInfo, classKind: ClassKind): Member { fun convertProperty(propertyInfo: PropertyInfo, classKind: ClassKind): Member {
@@ -544,7 +544,7 @@ class Converter private constructor(
val annotations = convertAnnotations(method) + convertThrows(method) val annotations = convertAnnotations(method) + convertThrows(method)
var modifiers = convertModifiers(method, classKind.isOpen()) var modifiers = convertModifiers(method, classKind.isOpen(), classKind == ClassKind.OBJECT)
val statementsToInsert = ArrayList<Statement>() val statementsToInsert = ArrayList<Statement>()
for (parameter in method.parameterList.parameters) { for (parameter in method.parameterList.parameters) {
@@ -735,7 +735,7 @@ class Converter private constructor(
return Identifier(identifier.text!!).assignPrototype(identifier) return Identifier(identifier.text!!).assignPrototype(identifier)
} }
fun convertModifiers(owner: PsiModifierListOwner, isMethodInOpenClass: Boolean): Modifiers { fun convertModifiers(owner: PsiModifierListOwner, isMethodInOpenClass: Boolean, isInObject: Boolean): Modifiers {
var modifiers = Modifiers(MODIFIERS_MAP.filter { owner.hasModifierProperty(it.first) }.map { it.second }) var modifiers = Modifiers(MODIFIERS_MAP.filter { owner.hasModifierProperty(it.first) }.map { it.second })
.assignPrototype(owner.modifierList, CommentsAndSpacesInheritance.NO_SPACES) .assignPrototype(owner.modifierList, CommentsAndSpacesInheritance.NO_SPACES)
@@ -752,10 +752,14 @@ class Converter private constructor(
if (owner.hasModifierProperty(PsiModifier.NATIVE)) if (owner.hasModifierProperty(PsiModifier.NATIVE))
modifiers = modifiers.with(Modifier.EXTERNAL) modifiers = modifiers.with(Modifier.EXTERNAL)
modifiers = modifiers.adaptForContainingClassVisibility(owner.containingClass).adaptProtectedVisibility(owner) modifiers = modifiers.adaptForObject(isInObject)
.adaptForContainingClassVisibility(owner.containingClass)
.adaptProtectedVisibility(owner)
} }
else if (owner is PsiField) { else if (owner is PsiField) {
modifiers = modifiers.adaptForContainingClassVisibility(owner.containingClass).adaptProtectedVisibility(owner) modifiers = modifiers.adaptForObject(isInObject)
.adaptForContainingClassVisibility(owner.containingClass)
.adaptProtectedVisibility(owner)
} }
else if (owner is PsiClass && owner.scope is PsiMethod) { else if (owner is PsiClass && owner.scope is PsiMethod) {
// Local class should not have visibility modifiers // Local class should not have visibility modifiers
@@ -765,6 +769,12 @@ class Converter private constructor(
return modifiers return modifiers
} }
private fun Modifiers.adaptForObject(isInObject: Boolean): Modifiers {
if (!isInObject) return this
if (!modifiers.contains(Modifier.PROTECTED)) return this
return without(Modifier.PROTECTED).with(Modifier.INTERNAL)
}
// to convert package local members in package local class into public member (when it's not override, open or abstract) // to convert package local members in package local class into public member (when it's not override, open or abstract)
private fun Modifiers.adaptForContainingClassVisibility(containingClass: PsiClass?): Modifiers { private fun Modifiers.adaptForContainingClassVisibility(containingClass: PsiClass?): Modifiers {
if (containingClass == null || !containingClass.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) return this if (containingClass == null || !containingClass.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) return this
@@ -85,7 +85,8 @@ class PropertyInfo(
companion object { companion object {
fun fromFieldWithNoAccessors(field: PsiField, converter: Converter): PropertyInfo { fun fromFieldWithNoAccessors(field: PsiField, converter: Converter): PropertyInfo {
val isVar = field.isVar(converter.referenceSearcher) val isVar = field.isVar(converter.referenceSearcher)
val modifiers = converter.convertModifiers(field, false) val isInObject = field.containingClass?.let { converter.shouldConvertIntoObject(it) } == true
val modifiers = converter.convertModifiers(field, false, isInObject)
return PropertyInfo(field.declarationIdentifier(), isVar, field.type, field, null, null, false, false, modifiers, null, null) return PropertyInfo(field.declarationIdentifier(), isVar, field.type, field, null, null, false, false, modifiers, null, null)
} }
} }
@@ -221,9 +222,9 @@ private class PropertyDetector(
val propertyAccess = modifiers.accessModifier() val propertyAccess = modifiers.accessModifier()
val setterAccess = if (setterInfo != null) val setterAccess = if (setterInfo != null)
converter.convertModifiers(setterInfo.method, false).accessModifier() converter.convertModifiers(setterInfo.method, false, false).accessModifier()
else if (field != null && field.isVar(converter.referenceSearcher)) else if (field != null && field.isVar(converter.referenceSearcher))
converter.convertModifiers(field, false).accessModifier() converter.convertModifiers(field, false, false).accessModifier()
else else
propertyAccess propertyAccess
val specialSetterAccess = setterAccess?.takeIf { it != propertyAccess } val specialSetterAccess = setterAccess?.takeIf { it != propertyAccess }
@@ -366,9 +367,9 @@ private class PropertyDetector(
} }
private fun convertModifiers(field: PsiField?, getMethod: PsiMethod?, setMethod: PsiMethod?, isOverride: Boolean): Modifiers { private fun convertModifiers(field: PsiField?, getMethod: PsiMethod?, setMethod: PsiMethod?, isOverride: Boolean): Modifiers {
val fieldModifiers = field?.let { converter.convertModifiers(it, false) } ?: Modifiers.Empty val fieldModifiers = field?.let { converter.convertModifiers(it, false, false) } ?: Modifiers.Empty
val getterModifiers = getMethod?.let { converter.convertModifiers(it, isOpenClass) } ?: Modifiers.Empty val getterModifiers = getMethod?.let { converter.convertModifiers(it, isOpenClass, false) } ?: Modifiers.Empty
val setterModifiers = setMethod?.let { converter.convertModifiers(it, isOpenClass) } ?: Modifiers.Empty val setterModifiers = setMethod?.let { converter.convertModifiers(it, isOpenClass, false) } ?: Modifiers.Empty
val modifiers = ArrayList<Modifier>() val modifiers = ArrayList<Modifier>()
+11
View File
@@ -0,0 +1,11 @@
class Util {
public static final String publicStr = "";
protected static final String protectedStr = "";
static final String packageStr = "";
private static final String privateStr = "";
public static void publicMethod() {}
protected static void protectedMethod() {}
static void packageMethod() {}
private static void privateMethod() {}
}
+11
View File
@@ -0,0 +1,11 @@
internal object Util {
val publicStr = ""
val protectedStr = ""
val packageStr = ""
private val privateStr = ""
fun publicMethod() {}
fun protectedMethod() {}
fun packageMethod() {}
private fun privateMethod() {}
}
+11
View File
@@ -0,0 +1,11 @@
public class Util {
public static final String publicStr = "";
protected static final String protectedStr = "";
static final String packageStr = "";
private static final String privateStr = "";
public static void publicMethod() {}
protected static void protectedMethod() {}
static void packageMethod() {}
private static void privateMethod() {}
}
+11
View File
@@ -0,0 +1,11 @@
object Util {
val publicStr = ""
internal val protectedStr = ""
internal val packageStr = ""
private val privateStr = ""
fun publicMethod() {}
internal fun protectedMethod() {}
internal fun packageMethod() {}
private fun privateMethod() {}
}
@@ -1018,6 +1018,18 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/class/utilityClass3.java"); String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/class/utilityClass3.java");
doTest(fileName); doTest(fileName);
} }
@TestMetadata("utilityClass4.java")
public void testUtilityClass4() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/class/utilityClass4.java");
doTest(fileName);
}
@TestMetadata("utilityClass5.java")
public void testUtilityClass5() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/class/utilityClass5.java");
doTest(fileName);
}
} }
@TestMetadata("j2k/testData/fileOrElement/classExpression") @TestMetadata("j2k/testData/fileOrElement/classExpression")
@@ -1018,6 +1018,18 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/class/utilityClass3.java"); String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/class/utilityClass3.java");
doTest(fileName); doTest(fileName);
} }
@TestMetadata("utilityClass4.java")
public void testUtilityClass4() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/class/utilityClass4.java");
doTest(fileName);
}
@TestMetadata("utilityClass5.java")
public void testUtilityClass5() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/class/utilityClass5.java");
doTest(fileName);
}
} }
@TestMetadata("j2k/testData/fileOrElement/classExpression") @TestMetadata("j2k/testData/fileOrElement/classExpression")