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.calls.tasks;
018
019 import com.google.common.collect.Lists;
020 import com.google.common.collect.Sets;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.jet.lang.descriptors.*;
023 import org.jetbrains.jet.lang.resolve.BindingTrace;
024 import org.jetbrains.jet.lang.resolve.name.Name;
025 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
026 import org.jetbrains.jet.lang.types.ErrorUtils;
027 import org.jetbrains.jet.lang.types.JetType;
028
029 import java.util.*;
030
031 import static org.jetbrains.jet.lang.resolve.LibrarySourceHacks.filterOutMembersFromLibrarySource;
032
033 @SuppressWarnings("unchecked")
034 public class CallableDescriptorCollectors<D extends CallableDescriptor> implements Iterable<CallableDescriptorCollector<D>> {
035 private static final CallableDescriptorCollector<FunctionDescriptor> FUNCTIONS_COLLECTOR =
036 new FilteredCollector<FunctionDescriptor>(new FunctionCollector());
037 private static final CallableDescriptorCollector<VariableDescriptor> VARIABLES_COLLECTOR =
038 new FilteredCollector<VariableDescriptor>(new VariableCollector());
039 private static final CallableDescriptorCollector<VariableDescriptor> PROPERTIES_COLLECTOR =
040 new FilteredCollector<VariableDescriptor>(new PropertyCollector());
041
042 public static final CallableDescriptorCollectors<CallableDescriptor> FUNCTIONS_AND_VARIABLES =
043 new CallableDescriptorCollectors(FUNCTIONS_COLLECTOR, VARIABLES_COLLECTOR);
044 public static final CallableDescriptorCollectors<CallableDescriptor> FUNCTIONS =
045 new CallableDescriptorCollectors(FUNCTIONS_COLLECTOR);
046 public static final CallableDescriptorCollectors<VariableDescriptor> VARIABLES =
047 new CallableDescriptorCollectors(VARIABLES_COLLECTOR);
048 public static final CallableDescriptorCollectors<VariableDescriptor> PROPERTIES =
049 new CallableDescriptorCollectors(PROPERTIES_COLLECTOR);
050
051 private static class FunctionCollector implements CallableDescriptorCollector<FunctionDescriptor> {
052
053 @NotNull
054 @Override
055 public Collection<FunctionDescriptor> getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
056 Set<FunctionDescriptor> functions = Sets.newLinkedHashSet();
057 for (FunctionDescriptor function : scope.getFunctions(name)) {
058 if (function.getReceiverParameter() == null) {
059 functions.add(function);
060 }
061 }
062 addConstructors(scope, name, functions);
063 return functions;
064 }
065
066 @NotNull
067 @Override
068 public Collection<FunctionDescriptor> getMembersByName(@NotNull JetType receiverType, Name name, @NotNull BindingTrace bindingTrace) {
069 JetScope receiverScope = receiverType.getMemberScope();
070 Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctions(name));
071 addConstructors(receiverScope, name, members);
072 return members;
073 }
074
075 @NotNull
076 @Override
077 public Collection<FunctionDescriptor> getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
078 return scope.getFunctions(name);
079 }
080
081 private static void addConstructors(JetScope scope, Name name, Collection<FunctionDescriptor> functions) {
082 ClassifierDescriptor classifier = scope.getClassifier(name);
083 if (!(classifier instanceof ClassDescriptor) || ErrorUtils.isError(classifier)) return;
084 ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
085 if (classDescriptor.getKind().isSingleton()) {
086 // Constructors of singletons shouldn't be callable from the code
087 return;
088 }
089 functions.addAll(classDescriptor.getConstructors());
090 }
091
092 @Override
093 public String toString() {
094 return "FUNCTIONS";
095 }
096 }
097
098 private static class VariableCollector implements CallableDescriptorCollector<VariableDescriptor> {
099
100 @NotNull
101 @Override
102 public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
103 VariableDescriptor localVariable = scope.getLocalVariable(name);
104 if (localVariable != null) {
105 return Collections.singleton(localVariable);
106 }
107
108 LinkedHashSet<VariableDescriptor> variables = Sets.newLinkedHashSet();
109 for (VariableDescriptor variable : scope.getProperties(name)) {
110 if (variable.getReceiverParameter() == null) {
111 variables.add(variable);
112 }
113 }
114 return variables;
115 }
116
117 @NotNull
118 @Override
119 public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiverType, Name name, @NotNull BindingTrace bindingTrace) {
120 return receiverType.getMemberScope().getProperties(name);
121 }
122
123 @NotNull
124 @Override
125 public Collection<VariableDescriptor> getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
126 Collection<VariableDescriptor> result = Sets.newLinkedHashSet();
127
128 VariableDescriptor localVariable = scope.getLocalVariable(name);
129 if (localVariable != null) {
130 result.add(localVariable);
131 }
132 result.addAll(scope.getProperties(name));
133 return result;
134 }
135
136 @Override
137 public String toString() {
138 return "VARIABLES";
139 }
140 }
141
142 private static class PropertyCollector implements CallableDescriptorCollector<VariableDescriptor> {
143 private static Collection<VariableDescriptor> filterProperties(Collection<? extends VariableDescriptor> variableDescriptors) {
144 ArrayList<VariableDescriptor> properties = Lists.newArrayList();
145 for (VariableDescriptor descriptor : variableDescriptors) {
146 if (descriptor instanceof PropertyDescriptor) {
147 properties.add(descriptor);
148 }
149 }
150 return properties;
151 }
152
153 @NotNull
154 @Override
155 public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
156 return filterProperties(VARIABLES_COLLECTOR.getNonExtensionsByName(scope, name, bindingTrace));
157 }
158
159 @NotNull
160 @Override
161 public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiver, Name name, @NotNull BindingTrace bindingTrace) {
162 return filterProperties(VARIABLES_COLLECTOR.getMembersByName(receiver, name, bindingTrace));
163 }
164
165 @NotNull
166 @Override
167 public Collection<VariableDescriptor> getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
168 return filterProperties(VARIABLES_COLLECTOR.getNonMembersByName(scope, name, bindingTrace));
169 }
170
171 @Override
172 public String toString() {
173 return "PROPERTIES";
174 }
175 }
176
177 private static class FilteredCollector<D extends CallableDescriptor> implements CallableDescriptorCollector<D> {
178 private final CallableDescriptorCollector<D> delegate;
179
180 private FilteredCollector(CallableDescriptorCollector<D> delegate) {
181 this.delegate = delegate;
182 }
183
184 @NotNull
185 @Override
186 public Collection<D> getNonExtensionsByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
187 return filterOutMembersFromLibrarySource(delegate.getNonExtensionsByName(scope, name, bindingTrace));
188 }
189
190 @NotNull
191 @Override
192 public Collection<D> getMembersByName(@NotNull JetType receiver, Name name, @NotNull BindingTrace bindingTrace) {
193 return filterOutMembersFromLibrarySource(delegate.getMembersByName(receiver, name, bindingTrace));
194 }
195
196 @NotNull
197 @Override
198 public Collection<D> getNonMembersByName(JetScope scope, Name name, @NotNull BindingTrace bindingTrace) {
199 return filterOutMembersFromLibrarySource(delegate.getNonMembersByName(scope, name, bindingTrace));
200 }
201
202 @Override
203 public String toString() {
204 return delegate.toString();
205 }
206 }
207
208 private final Collection<CallableDescriptorCollector<D>> collectors;
209
210 private CallableDescriptorCollectors(CallableDescriptorCollector<D>... collectors) {
211 this.collectors = Lists.newArrayList(collectors);
212 }
213
214 @NotNull
215 @Override
216 public Iterator<CallableDescriptorCollector<D>> iterator() {
217 return collectors.iterator();
218 }
219 }