Support visibility for protected static members

#KT-2999 Fixed
This commit is contained in:
Natalia.Ukhorskaya
2013-01-24 18:41:26 +04:00
parent f9ae4f58b8
commit e37cb461f6
32 changed files with 401 additions and 12 deletions
@@ -102,7 +102,7 @@ public class SpecialFiles {
excludedFiles.add("forwardTypeParameter.jet"); // Commented
excludedFiles.add("kt259.jet"); // Commented
excludedFiles.add("classObjectMethod.jet"); // Commented
excludedFiles.add("inRangeConditionsInWhen.jet"); // Commented
excludedFiles.add("kt1592.kt"); // Codegen don't execute blackBoxFile() on it
@@ -115,7 +115,6 @@ public class SpecialFiles {
excludedFiles.add("kt684.jet"); // StackOverflow with StringBuilder (escape())
excludedFiles.add("kt344.jet"); // Bug KT-2251
excludedFiles.add("kt529.kt"); // Bug
excludedFiles.add("noClassObjectForJavaClass.kt");
@@ -125,6 +124,20 @@ public class SpecialFiles {
excludedFiles.add("nestedInPackage.kt"); // Custom packages are not supported
excludedFiles.add("importNestedClass.kt"); // Won't work when moved to another package
excludedFiles.add("protectedStaticClass.kt"); // Java
excludedFiles.add("protectedStaticClass2.kt"); // Java
excludedFiles.add("protectedStaticFun.kt"); // Java
excludedFiles.add("protectedStaticFunCallInConstructor.kt"); // Java
excludedFiles.add("protectedStaticFunClassObject.kt"); // Java
excludedFiles.add("protectedStaticFunGenericClass.kt"); // Java
excludedFiles.add("protectedStaticFunNestedStaticClass.kt"); // Java
excludedFiles.add("protectedStaticFunNestedStaticClass2.kt"); // Java
excludedFiles.add("protectedStaticFunNestedStaticGenericClass.kt"); // Java
excludedFiles.add("protectedStaticFunNotDirectSuperClass.kt"); // Java
excludedFiles.add("protectedStaticFunObject.kt"); // Java
excludedFiles.add("protectedStaticProperty.kt"); // Java
}
private SpecialFiles() {
@@ -68,6 +68,7 @@ public class AsmUtil {
private static final Map<Visibility, Integer> visibilityToAccessFlag = ImmutableMap.<Visibility, Integer>builder()
.put(Visibilities.PRIVATE, ACC_PRIVATE)
.put(Visibilities.PROTECTED, ACC_PROTECTED)
.put(JavaDescriptorResolver.PROTECTED_STATIC_VISIBILITY, ACC_PROTECTED)
.put(Visibilities.PUBLIC, ACC_PUBLIC)
.put(Visibilities.INTERNAL, ACC_PUBLIC)
.put(Visibilities.LOCAL, NO_FLAG_LOCAL)
@@ -84,11 +84,20 @@ public final class DescriptorResolverUtils {
return Visibilities.INTERNAL;
}
}
return modifierListOwner.hasModifierProperty(PsiModifier.PUBLIC) ? Visibilities.PUBLIC :
(modifierListOwner.hasModifierProperty(PsiModifier.PRIVATE) ? Visibilities.PRIVATE :
(modifierListOwner.hasModifierProperty(PsiModifier.PROTECTED) ? Visibilities.PROTECTED :
//Visibilities.PUBLIC));
JavaDescriptorResolver.PACKAGE_VISIBILITY));
if (modifierListOwner.hasModifierProperty(PsiModifier.PUBLIC)) {
return Visibilities.PUBLIC;
}
if (modifierListOwner.hasModifierProperty(PsiModifier.PRIVATE)) {
return Visibilities.PRIVATE;
}
if (modifierListOwner.hasModifierProperty(PsiModifier.PROTECTED)) {
if (modifierListOwner.hasModifierProperty(PsiModifier.STATIC)) {
return JavaDescriptorResolver.PROTECTED_STATIC_VISIBILITY;
}
return Visibilities.PROTECTED;
}
return JavaDescriptorResolver.PACKAGE_VISIBILITY;
}
@Nullable
@@ -55,6 +55,35 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
}
};
public static final Visibility PROTECTED_STATIC_VISIBILITY = new Visibility("protected_static", false) {
@Override
protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
if (fromClass == null) return false;
ClassDescriptor whatClass;
// protected static class
if (what instanceof ClassDescriptor) {
DeclarationDescriptor containingDeclaration = what.getContainingDeclaration();
assert containingDeclaration instanceof ClassDescriptor : "Only static nested classes can have protected_static visibility";
whatClass = (ClassDescriptor) containingDeclaration;
}
// protected static function or property
else {
DeclarationDescriptor whatDeclarationDescriptor = what.getContainingDeclaration();
assert whatDeclarationDescriptor instanceof NamespaceDescriptor : "Only static declarations can have protected_static visibility";
whatClass = DescriptorUtils.getClassForCorrespondingJavaNamespace((NamespaceDescriptor) whatDeclarationDescriptor);
}
assert whatClass != null : "Couldn't find ClassDescriptor for protected static member " + what;
if (DescriptorUtils.isSubclass(fromClass, whatClass)) {
return true;
}
return isVisible(what, fromClass.getContainingDeclaration());
}
};
private JavaPropertyResolver propertiesResolver;
private JavaClassResolver classResolver;
private JavaConstructorResolver constructorResolver;
@@ -23,17 +23,13 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetFunction;
import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
@@ -444,4 +440,32 @@ public class DescriptorUtils {
DeclarationDescriptor containingDeclaration = scope.getContainingDeclaration();
return getParentOfType(containingDeclaration, ClassDescriptor.class, false);
}
@Nullable
public static ClassDescriptor getClassForCorrespondingJavaNamespace(@NotNull NamespaceDescriptor correspondingNamespace) {
NamespaceDescriptorParent containingDeclaration = correspondingNamespace.getContainingDeclaration();
if (!(containingDeclaration instanceof NamespaceDescriptor)) {
return null;
}
NamespaceDescriptor namespaceDescriptor = (NamespaceDescriptor) containingDeclaration;
ClassifierDescriptor classDescriptor = namespaceDescriptor.getMemberScope().getClassifier(correspondingNamespace.getName());
if (classDescriptor != null && classDescriptor instanceof ClassDescriptor) {
return (ClassDescriptor) classDescriptor;
}
ClassDescriptor classDescriptorForOuterClass = getClassForCorrespondingJavaNamespace(namespaceDescriptor);
if (classDescriptorForOuterClass == null) {
return null;
}
ClassifierDescriptor innerClassDescriptor =
classDescriptorForOuterClass.getUnsubstitutedInnerClassesScope().getClassifier(correspondingNamespace.getName());
if (innerClassDescriptor instanceof ClassDescriptor) {
return (ClassDescriptor) innerClassDescriptor;
}
return null;
}
}
@@ -0,0 +1,10 @@
import java.lang.String;
public class protectedStaticClass {
protected static class Inner {
public Inner() {}
public String foo() {
return "OK";
}
}
}
@@ -0,0 +1,9 @@
class Derived(): protectedStaticClass() {
fun test(): String {
return protectedStaticClass.Inner().foo()!!
}
}
fun box(): String {
return Derived().test()
}
@@ -0,0 +1,14 @@
import java.lang.String;
public class protectedStaticClass2 {
public static class A {
protected static class B {
public B() {
}
public String foo() {
return "OK";
}
}
}
}
@@ -0,0 +1,9 @@
class Derived(): protectedStaticClass2.A() {
fun test(): String {
return protectedStaticClass2.A.B().foo()!!
}
}
fun box(): String {
return Derived().test()
}
@@ -0,0 +1,5 @@
public class protectedStaticFun {
protected static String protectedFun() {
return "OK";
}
}
@@ -0,0 +1,9 @@
class Derived(): protectedStaticFun() {
fun test(): String {
return protectedStaticFun.protectedFun()!!
}
}
fun box(): String {
return Derived().test()
}
@@ -0,0 +1,14 @@
import java.lang.String;
public class protectedStaticFunCallInConstructor {
protected final String protectedProperty;
public protectedStaticFunCallInConstructor(String str) {
protectedProperty = str;
}
protected static String protectedFun() {
return "OK";
}
}
@@ -0,0 +1,9 @@
class A: protectedStaticFunCallInConstructor(protectedStaticFunCallInConstructor.protectedFun()) {
fun test(): String {
return protectedProperty!!
}
}
fun box(): String {
return A().test()
}
@@ -0,0 +1,6 @@
public class protectedStaticFunClassObject {
protected static String protectedFun() {
return "OK";
}
}
@@ -0,0 +1,11 @@
class A {
class object: protectedStaticFunClassObject() {
fun test(): String {
return protectedStaticFunClassObject.protectedFun()!!
}
}
}
fun box(): String {
return A.test()
}
@@ -0,0 +1,5 @@
public class protectedStaticFunGenericClass<T> {
protected static String protectedFun() {
return "OK";
}
}
@@ -0,0 +1,9 @@
class Derived(): protectedStaticFunGenericClass<String>() {
fun test(): String {
return protectedStaticFunGenericClass.protectedFun()!!
}
}
fun box(): String {
return Derived().test()
}
@@ -0,0 +1,7 @@
public class protectedStaticFunNestedStaticClass {
public static class Inner {
protected static String protectedFun() {
return "OK";
}
}
}
@@ -0,0 +1,9 @@
class Derived(): protectedStaticFunNestedStaticClass.Inner() {
fun test(): String {
return protectedStaticFunNestedStaticClass.Inner.protectedFun()!!
}
}
fun box(): String {
return Derived().test()
}
@@ -0,0 +1,9 @@
public class protectedStaticFunNestedStaticClass2 {
public static class A {
public static class B {
protected static String protectedFun() {
return "OK";
}
}
}
}
@@ -0,0 +1,9 @@
class Derived(): protectedStaticFunNestedStaticClass2.A.B() {
fun test(): String {
return protectedStaticFunNestedStaticClass2.A.B.protectedFun()!!
}
}
fun box(): String {
return Derived().test()
}
@@ -0,0 +1,7 @@
public class protectedStaticFunNestedStaticGenericClass<T> {
public static class Inner<S> {
protected static String protectedFun() {
return "OK";
}
}
}
@@ -0,0 +1,9 @@
class Derived(): protectedStaticFunNestedStaticGenericClass<String>.Inner<String>() {
fun test(): String {
return protectedStaticFunNestedStaticGenericClass.Inner.protectedFun()!!
}
}
fun box(): String {
return Derived().test()
}
@@ -0,0 +1,5 @@
public class protectedStaticFunNotDirectSuperClass {
protected static String protectedFun() {
return "OK";
}
}
@@ -0,0 +1,12 @@
open class A : protectedStaticFunNotDirectSuperClass() {}
class Derived(): A() {
fun test(): String {
return protectedStaticFunNotDirectSuperClass.protectedFun()!!
}
}
fun box(): String {
return Derived().test()
}
@@ -0,0 +1,6 @@
public class protectedStaticFunObject {
protected static String protectedFun() {
return "OK";
}
}
@@ -0,0 +1,9 @@
object A: protectedStaticFunObject() {
fun test(): String {
return protectedStaticFunObject.protectedFun()!!
}
}
fun box(): String {
return A.test()
}
@@ -0,0 +1,3 @@
public class protectedStaticProperty {
protected static final String protectedProperty = "OK";
}
@@ -0,0 +1,10 @@
class Derived(): protectedStaticProperty() {
fun test(): String {
return protectedStaticProperty.protectedProperty!!
}
}
fun box(): String {
return Derived().test()
}
@@ -285,6 +285,10 @@ public abstract class CodegenTestCase extends UsefulTestCase {
}
}
protected void blackBoxFileWithJavaByFullPath(@NotNull String ktFile) throws Exception {
blackBoxFileWithJava(ktFile.substring("compiler/testData/codegen/".length()), false);
}
protected void blackBoxFileWithJava(@NotNull String ktFile) throws Exception {
blackBoxFileWithJava(ktFile, false);
}
@@ -0,0 +1,97 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.generated;
import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestSuite;
import java.io.File;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.test.InnerTestClasses;
import org.jetbrains.jet.test.TestMetadata;
import org.jetbrains.jet.codegen.generated.AbstractCodegenTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/visibility/withJava/protected_static")
public class VisibilityGenWithJavaTestGenerated extends AbstractCodegenTest {
public void testAllFilesPresentInProtected_static() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/visibility/withJava/protected_static"), "kt", true);
}
@TestMetadata("protectedStaticClass.kt")
public void testProtectedStaticClass() throws Exception {
blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/withJava/protected_static/protectedStaticClass.kt");
}
@TestMetadata("protectedStaticClass2.kt")
public void testProtectedStaticClass2() throws Exception {
blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/withJava/protected_static/protectedStaticClass2.kt");
}
@TestMetadata("protectedStaticFun.kt")
public void testProtectedStaticFun() throws Exception {
blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/withJava/protected_static/protectedStaticFun.kt");
}
@TestMetadata("protectedStaticFunCallInConstructor.kt")
public void testProtectedStaticFunCallInConstructor() throws Exception {
blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/withJava/protected_static/protectedStaticFunCallInConstructor.kt");
}
@TestMetadata("protectedStaticFunClassObject.kt")
public void testProtectedStaticFunClassObject() throws Exception {
blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/withJava/protected_static/protectedStaticFunClassObject.kt");
}
@TestMetadata("protectedStaticFunGenericClass.kt")
public void testProtectedStaticFunGenericClass() throws Exception {
blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/withJava/protected_static/protectedStaticFunGenericClass.kt");
}
@TestMetadata("protectedStaticFunNestedStaticClass.kt")
public void testProtectedStaticFunNestedStaticClass() throws Exception {
blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/withJava/protected_static/protectedStaticFunNestedStaticClass.kt");
}
@TestMetadata("protectedStaticFunNestedStaticClass2.kt")
public void testProtectedStaticFunNestedStaticClass2() throws Exception {
blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/withJava/protected_static/protectedStaticFunNestedStaticClass2.kt");
}
@TestMetadata("protectedStaticFunNestedStaticGenericClass.kt")
public void testProtectedStaticFunNestedStaticGenericClass() throws Exception {
blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/withJava/protected_static/protectedStaticFunNestedStaticGenericClass.kt");
}
@TestMetadata("protectedStaticFunNotDirectSuperClass.kt")
public void testProtectedStaticFunNotDirectSuperClass() throws Exception {
blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/withJava/protected_static/protectedStaticFunNotDirectSuperClass.kt");
}
@TestMetadata("protectedStaticFunObject.kt")
public void testProtectedStaticFunObject() throws Exception {
blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/withJava/protected_static/protectedStaticFunObject.kt");
}
@TestMetadata("protectedStaticProperty.kt")
public void testProtectedStaticProperty() throws Exception {
blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/withJava/protected_static/protectedStaticProperty.kt");
}
}
@@ -95,6 +95,13 @@ public class GenerateTests {
testModel("compiler/testData/codegen/multiDecl", "blackBoxFileByFullPath")
);
generateTest(
"compiler/tests/",
"VisibilityGenWithJavaTestGenerated",
AbstractCodegenTest.class,
testModel("compiler/testData/codegen/visibility/withJava/protected_static", "blackBoxFileWithJavaByFullPath")
);
generateTest(
"compiler/tests/",
"WriteFlagsTestGenerated",