001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.lang.resolve.java;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.jet.lang.descriptors.*;
022 import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent;
023 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
024
025 public class JavaVisibilities {
026 private JavaVisibilities() {
027 }
028
029 public static final Visibility PACKAGE_VISIBILITY = new Visibility("package", false) {
030 @Override
031 protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
032 return isInSameNamespace(what, from);
033 }
034
035 @Override
036 protected Integer compareTo(@NotNull Visibility visibility) {
037 if (this == visibility) return 0;
038 if (visibility == Visibilities.PRIVATE) return 1;
039 return -1;
040 }
041
042 @Override
043 public String toString() {
044 return "public/*package*/";
045 }
046
047 @NotNull
048 @Override
049 public Visibility normalize() {
050 return Visibilities.INTERNAL;
051 }
052 };
053
054 public static final Visibility PROTECTED_STATIC_VISIBILITY = new Visibility("protected_static", false) {
055 @Override
056 protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
057 ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
058 if (fromClass == null) return false;
059
060 ClassDescriptor whatClass;
061 // protected static class
062 if (what instanceof ClassDescriptor) {
063 DeclarationDescriptor containingDeclaration = what.getContainingDeclaration();
064 assert containingDeclaration instanceof ClassDescriptor : "Only static nested classes can have protected_static visibility";
065 whatClass = (ClassDescriptor) containingDeclaration;
066 }
067 // protected static function or property
068 else {
069 DeclarationDescriptor whatDeclarationDescriptor = what.getContainingDeclaration();
070 assert whatDeclarationDescriptor instanceof NamespaceDescriptor : "Only static declarations can have protected_static visibility";
071 whatClass = getClassForCorrespondingJavaNamespace((NamespaceDescriptor) whatDeclarationDescriptor);
072 }
073
074 assert whatClass != null : "Couldn't find ClassDescriptor for protected static member " + what;
075
076 if (DescriptorUtils.isSubclass(fromClass, whatClass)) {
077 return true;
078 }
079 return isVisible(what, fromClass.getContainingDeclaration());
080 }
081
082 @Override
083 public String toString() {
084 return "protected/*protected static*/";
085 }
086
087 @NotNull
088 @Override
089 public Visibility normalize() {
090 return Visibilities.PROTECTED;
091 }
092 };
093
094 public static final Visibility PROTECTED_AND_PACKAGE = new Visibility("protected_and_package", false) {
095 @Override
096 protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
097 if (isInSameNamespace(what, from)) {
098 return true;
099 }
100
101 ClassDescriptor whatClass = DescriptorUtils.getParentOfType(what, ClassDescriptor.class, false);
102 if (whatClass == null) return false;
103
104 ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
105 if (fromClass == null) return false;
106
107 if (DescriptorUtils.isSubclass(fromClass, whatClass)) {
108 return true;
109 }
110 return isVisible(what, fromClass.getContainingDeclaration());
111 }
112
113 @Override
114 protected Integer compareTo(@NotNull Visibility visibility) {
115 if (this == visibility) return 0;
116 if (visibility == Visibilities.INTERNAL) return null;
117 if (visibility == Visibilities.PRIVATE) return 1;
118 return -1;
119 }
120
121 @Override
122 public String toString() {
123 return "protected/*protected and package*/";
124 }
125
126 @NotNull
127 @Override
128 public Visibility normalize() {
129 return Visibilities.PROTECTED;
130 }
131 };
132
133 private static boolean isInSameNamespace(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) {
134 NamespaceDescriptor whatPackage = DescriptorUtils.getParentOfType(first, NamespaceDescriptor.class, false);
135 NamespaceDescriptor fromPackage = DescriptorUtils.getParentOfType(second, NamespaceDescriptor.class, false);
136 return fromPackage != null && whatPackage != null && whatPackage.equals(fromPackage);
137 }
138
139 @Nullable
140 private static ClassDescriptor getClassForCorrespondingJavaNamespace(@NotNull NamespaceDescriptor correspondingNamespace) {
141 NamespaceDescriptorParent containingDeclaration = correspondingNamespace.getContainingDeclaration();
142 if (!(containingDeclaration instanceof NamespaceDescriptor)) {
143 return null;
144 }
145
146 NamespaceDescriptor namespaceDescriptor = (NamespaceDescriptor) containingDeclaration;
147
148 ClassifierDescriptor classDescriptor = namespaceDescriptor.getMemberScope().getClassifier(correspondingNamespace.getName());
149 if (classDescriptor != null && classDescriptor instanceof ClassDescriptor) {
150 return (ClassDescriptor) classDescriptor;
151 }
152
153 ClassDescriptor classDescriptorForOuterClass = getClassForCorrespondingJavaNamespace(namespaceDescriptor);
154 if (classDescriptorForOuterClass == null) {
155 return null;
156 }
157
158 ClassifierDescriptor innerClassDescriptor =
159 classDescriptorForOuterClass.getUnsubstitutedInnerClassesScope().getClassifier(correspondingNamespace.getName());
160 if (innerClassDescriptor instanceof ClassDescriptor) {
161 return (ClassDescriptor) innerClassDescriptor;
162 }
163 return null;
164 }
165 }