001    /*
002     * Copyright 2010-2015 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.kotlin.load.java;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.kotlin.descriptors.*;
021    import org.jetbrains.kotlin.resolve.DescriptorUtils;
022    import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
023    
024    public class JavaVisibilities {
025        private JavaVisibilities() {
026        }
027    
028        public static final Visibility PACKAGE_VISIBILITY = new Visibility("package", false) {
029            @Override
030            public boolean isVisible(@NotNull ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
031                return areInSamePackage(what, from);
032            }
033    
034            @Override
035            public boolean mustCheckInImports() {
036                return true;
037            }
038    
039            @Override
040            protected Integer compareTo(@NotNull Visibility visibility) {
041                if (this == visibility) return 0;
042                if (Visibilities.isPrivate(visibility)) return 1;
043                return -1;
044            }
045    
046            @NotNull
047            @Override
048            public String getDisplayName() {
049                return "public/*package*/";
050            }
051    
052            @NotNull
053            @Override
054            public Visibility normalize() {
055                return Visibilities.INTERNAL;
056            }
057        };
058    
059        public static final Visibility PROTECTED_STATIC_VISIBILITY = new Visibility("protected_static", true) {
060            @Override
061            public boolean isVisible(@NotNull ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
062                if (areInSamePackage(what, from)) {
063                    return true;
064                }
065    
066                ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
067                if (fromClass == null) return false;
068    
069                DeclarationDescriptor containingDeclaration = what.getContainingDeclaration();
070                assert containingDeclaration instanceof ClassDescriptor : "Only class members can have protected_static visibility";
071                ClassDescriptor whatClass = (ClassDescriptor) containingDeclaration;
072    
073                if (DescriptorUtils.isSubclass(fromClass, whatClass)) {
074                    return true;
075                }
076                return isVisible(receiver, what, fromClass.getContainingDeclaration());
077            }
078    
079            @Override
080            public boolean mustCheckInImports() {
081                return false;
082            }
083    
084            @NotNull
085            @Override
086            public String getDisplayName() {
087                return "protected/*protected static*/";
088            }
089    
090            @NotNull
091            @Override
092            public Visibility normalize() {
093                return Visibilities.PROTECTED;
094            }
095        };
096    
097        public static final Visibility PROTECTED_AND_PACKAGE = new Visibility("protected_and_package", true) {
098            @Override
099            public boolean isVisible(@NotNull ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
100                if (areInSamePackage(what, from)) {
101                    return true;
102                }
103    
104                ClassDescriptor whatClass = DescriptorUtils.getParentOfType(what, ClassDescriptor.class, false);
105                if (whatClass == null) return false;
106    
107                ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
108                if (fromClass == null) return false;
109    
110                if (DescriptorUtils.isSubclass(fromClass, whatClass)) {
111                    return true;
112                }
113                return isVisible(receiver, what, fromClass.getContainingDeclaration());
114            }
115    
116            @Override
117            public boolean mustCheckInImports() {
118                return false;
119            }
120    
121            @Override
122            protected Integer compareTo(@NotNull Visibility visibility) {
123                if (this == visibility) return 0;
124                if (visibility == Visibilities.INTERNAL) return null;
125                if (Visibilities.isPrivate(visibility)) return 1;
126                return -1;
127            }
128    
129            @NotNull
130            @Override
131            public String getDisplayName() {
132                return "protected/*protected and package*/";
133            }
134    
135            @NotNull
136            @Override
137            public Visibility normalize() {
138                return Visibilities.PROTECTED;
139            }
140        };
141    
142        private static boolean areInSamePackage(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) {
143            PackageFragmentDescriptor whatPackage = DescriptorUtils.getParentOfType(first, PackageFragmentDescriptor.class, false);
144            PackageFragmentDescriptor fromPackage = DescriptorUtils.getParentOfType(second, PackageFragmentDescriptor.class, false);
145            return fromPackage != null && whatPackage != null && whatPackage.getFqName().equals(fromPackage.getFqName());
146        }
147    }