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
017package org.jetbrains.jet.lang.resolve.java;
018
019import org.jetbrains.annotations.NotNull;
020import org.jetbrains.annotations.Nullable;
021import org.jetbrains.jet.lang.descriptors.*;
022import org.jetbrains.jet.lang.resolve.DescriptorUtils;
023import org.jetbrains.jet.lang.resolve.java.provider.ClassPsiDeclarationProvider;
024import org.jetbrains.jet.lang.resolve.java.provider.PackagePsiDeclarationProvider;
025import org.jetbrains.jet.lang.resolve.java.provider.PsiDeclarationProvider;
026import org.jetbrains.jet.lang.resolve.java.resolver.*;
027import org.jetbrains.jet.lang.resolve.name.FqName;
028import org.jetbrains.jet.lang.resolve.name.Name;
029import org.jetbrains.jet.lang.resolve.scopes.JetScope;
030import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver;
031import org.jetbrains.jet.lang.types.JetType;
032
033import javax.inject.Inject;
034import java.util.Collection;
035import java.util.List;
036import java.util.Set;
037
038public class JavaDescriptorResolver implements DependencyClassByQualifiedNameResolver {
039
040    public static final Name JAVA_ROOT = Name.special("<java_root>");
041
042    public static final Visibility PACKAGE_VISIBILITY = new Visibility("package", false) {
043        @Override
044        protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
045            return DescriptorUtils.isInSameNamespace(what, from);
046        }
047
048        @Override
049        protected Integer compareTo(@NotNull Visibility visibility) {
050            if (this == visibility) return 0;
051            if (visibility == Visibilities.PRIVATE) return 1;
052            return -1;
053        }
054
055        @Override
056        public String toString() {
057            return "public/*package*/";
058        }
059
060        @NotNull
061        @Override
062        public Visibility normalize() {
063            return Visibilities.INTERNAL;
064        }
065    };
066
067    public static final Visibility PROTECTED_STATIC_VISIBILITY = new Visibility("protected_static", false) {
068        @Override
069        protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
070            ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
071            if (fromClass == null) return false;
072
073            ClassDescriptor whatClass;
074            // protected static class
075            if (what instanceof ClassDescriptor) {
076                DeclarationDescriptor containingDeclaration = what.getContainingDeclaration();
077                assert containingDeclaration instanceof ClassDescriptor : "Only static nested classes can have protected_static visibility";
078                whatClass = (ClassDescriptor) containingDeclaration;
079            }
080            // protected static function or property
081            else {
082                DeclarationDescriptor whatDeclarationDescriptor = what.getContainingDeclaration();
083                assert whatDeclarationDescriptor instanceof NamespaceDescriptor : "Only static declarations can have protected_static visibility";
084                whatClass = DescriptorUtils.getClassForCorrespondingJavaNamespace((NamespaceDescriptor) whatDeclarationDescriptor);
085            }
086
087            assert whatClass != null : "Couldn't find ClassDescriptor for protected static member " + what;
088
089            if (DescriptorUtils.isSubclass(fromClass, whatClass)) {
090                return true;
091            }
092            return isVisible(what, fromClass.getContainingDeclaration());
093        }
094
095        @Override
096        public String toString() {
097            return "protected/*protected static*/";
098        }
099
100        @NotNull
101        @Override
102        public Visibility normalize() {
103            return Visibilities.PROTECTED;
104        }
105    };
106
107    public static final Visibility PROTECTED_AND_PACKAGE = new Visibility("protected_and_package", false) {
108        @Override
109        protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
110            if (DescriptorUtils.isInSameNamespace(what, from)) {
111                return true;
112            }
113
114            ClassDescriptor whatClass = DescriptorUtils.getParentOfType(what, ClassDescriptor.class, false);
115            if (whatClass == null) return false;
116
117            ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
118            if (fromClass == null) return false;
119
120            if (DescriptorUtils.isSubclass(fromClass, whatClass)) {
121                return true;
122            }
123            return isVisible(what, fromClass.getContainingDeclaration());
124        }
125
126        @Override
127        protected Integer compareTo(@NotNull Visibility visibility) {
128            if (this == visibility) return 0;
129            if (visibility == Visibilities.INTERNAL) return null;
130            if (visibility == Visibilities.PRIVATE) return 1;
131            return -1;
132        }
133
134        @Override
135        public String toString() {
136            return "protected/*protected and package*/";
137        }
138
139        @NotNull
140        @Override
141        public Visibility normalize() {
142            return Visibilities.PROTECTED;
143        }
144    };
145
146    private JavaPropertyResolver propertiesResolver;
147    private JavaClassResolver classResolver;
148    private JavaConstructorResolver constructorResolver;
149    private JavaFunctionResolver functionResolver;
150    private JavaNamespaceResolver namespaceResolver;
151    private JavaInnerClassResolver innerClassResolver;
152
153    @Inject
154    public void setFunctionResolver(JavaFunctionResolver functionResolver) {
155        this.functionResolver = functionResolver;
156    }
157
158    @Inject
159    public void setClassResolver(JavaClassResolver classResolver) {
160        this.classResolver = classResolver;
161    }
162
163    @Inject
164    public void setNamespaceResolver(JavaNamespaceResolver namespaceResolver) {
165        this.namespaceResolver = namespaceResolver;
166    }
167
168    @Inject
169    public void setPropertiesResolver(JavaPropertyResolver propertiesResolver) {
170        this.propertiesResolver = propertiesResolver;
171    }
172
173    @Inject
174    public void setConstructorResolver(JavaConstructorResolver constructorResolver) {
175        this.constructorResolver = constructorResolver;
176    }
177
178    @Inject
179    public void setInnerClassResolver(JavaInnerClassResolver innerClassResolver) {
180        this.innerClassResolver = innerClassResolver;
181    }
182
183    @Nullable
184    public ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
185        return classResolver.resolveClass(qualifiedName, searchRule);
186    }
187
188    @Override
189    public ClassDescriptor resolveClass(@NotNull FqName qualifiedName) {
190        return classResolver.resolveClass(qualifiedName);
191    }
192
193    @NotNull
194    public Collection<ConstructorDescriptor> resolveConstructors(
195            @NotNull ClassPsiDeclarationProvider classData, @NotNull ClassDescriptor classDescriptor
196    ) {
197        return constructorResolver.resolveConstructors(classData, classDescriptor);
198    }
199
200    @Nullable
201    public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
202        return namespaceResolver.resolveNamespace(qualifiedName, searchRule);
203    }
204
205    @Override
206    public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName) {
207        return namespaceResolver.resolveNamespace(qualifiedName);
208    }
209
210    @Nullable
211    public JetScope getJavaPackageScope(@NotNull NamespaceDescriptor namespaceDescriptor) {
212        return namespaceResolver.getJavaPackageScopeForExistingNamespaceDescriptor(namespaceDescriptor);
213    }
214
215    @NotNull
216    public Set<VariableDescriptor> resolveFieldGroupByName(
217            @NotNull Name name,
218            @NotNull PsiDeclarationProvider data,
219            @NotNull ClassOrNamespaceDescriptor ownerDescriptor
220    ) {
221        return propertiesResolver.resolveFieldGroupByName(name, data, ownerDescriptor);
222    }
223
224    @Nullable
225    public ClassDescriptor resolveClass(@NotNull FqName name, @NotNull DescriptorSearchRule searchRule, @NotNull PostponedTasks tasks) {
226        return classResolver.resolveClass(name, searchRule, tasks);
227    }
228
229    public static class ValueParameterDescriptors {
230        private final JetType receiverType;
231        private final List<ValueParameterDescriptor> descriptors;
232
233        public ValueParameterDescriptors(@Nullable JetType receiverType, @NotNull List<ValueParameterDescriptor> descriptors) {
234            this.receiverType = receiverType;
235            this.descriptors = descriptors;
236        }
237
238        @Nullable
239        public JetType getReceiverType() {
240            return receiverType;
241        }
242
243        @NotNull
244        public List<ValueParameterDescriptor> getDescriptors() {
245            return descriptors;
246        }
247    }
248
249    @NotNull
250    public Set<FunctionDescriptor> resolveFunctionGroup(
251            @NotNull Name methodName,
252            @NotNull ClassPsiDeclarationProvider scopeData,
253            @NotNull ClassOrNamespaceDescriptor ownerDescriptor
254    ) {
255        return functionResolver.resolveFunctionGroup(methodName, scopeData, ownerDescriptor);
256    }
257
258    @NotNull
259    public Set<FunctionDescriptor> resolveFunctionGroup(
260            @NotNull Name methodName,
261            @NotNull PackagePsiDeclarationProvider scopeData,
262            @NotNull NamespaceDescriptor ownerDescriptor
263    ) {
264        return functionResolver.resolveFunctionGroup(methodName, scopeData, ownerDescriptor);
265    }
266
267    @NotNull
268    public List<ClassDescriptor> resolveInnerClasses(@NotNull ClassPsiDeclarationProvider declarationProvider) {
269        return innerClassResolver.resolveInnerClasses(declarationProvider);
270    }
271}