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.DescriptorUtils;
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    public class CallableDescriptorCollectors {
032        public static CallableDescriptorCollector<FunctionDescriptor> FUNCTIONS = new FunctionCollector();
033        public static CallableDescriptorCollector<VariableDescriptor> VARIABLES = new VariableCollector();
034        public static CallableDescriptorCollector<VariableDescriptor> PROPERTIES = new PropertyCollector();
035        public static List<CallableDescriptorCollector<? extends CallableDescriptor>> FUNCTIONS_AND_VARIABLES =
036                Lists.newArrayList(FUNCTIONS, VARIABLES);
037    
038        private static class FunctionCollector implements CallableDescriptorCollector<FunctionDescriptor> {
039    
040            @NotNull
041            @Override
042            public Collection<FunctionDescriptor> getNonExtensionsByName(JetScope scope, Name name) {
043                Set<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctions(name));
044                for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) {
045                    FunctionDescriptor functionDescriptor = iterator.next();
046                    if (functionDescriptor.getReceiverParameter() != null) {
047                        iterator.remove();
048                    }
049                }
050                addConstructors(scope, name, functions);
051                return functions;
052            }
053    
054            @NotNull
055            @Override
056            public Collection<FunctionDescriptor> getMembersByName(@NotNull JetType receiverType, Name name) {
057                JetScope receiverScope = receiverType.getMemberScope();
058                Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctions(name));
059                addConstructors(receiverScope, name, members);
060                return members;
061            }
062    
063            @NotNull
064            @Override
065            public Collection<FunctionDescriptor> getNonMembersByName(JetScope scope, Name name) {
066                return scope.getFunctions(name);
067            }
068    
069            private static void addConstructors(JetScope scope, Name name, Collection<FunctionDescriptor> functions) {
070                ClassifierDescriptor classifier = scope.getClassifier(name);
071                if (classifier instanceof ClassDescriptor && !ErrorUtils.isError(classifier.getTypeConstructor())) {
072                    ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
073                    functions.addAll(classDescriptor.getConstructors());
074                }
075            }
076    
077            @Override
078            public String toString() {
079                return "FUNCTIONS";
080            }
081        }
082    
083        private static class VariableCollector implements CallableDescriptorCollector<VariableDescriptor> {
084    
085            @NotNull
086            @Override
087            public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, Name name) {
088                VariableDescriptor descriptor = scope.getLocalVariable(name);
089                if (descriptor == null) {
090                    descriptor = DescriptorUtils.filterNonExtensionProperty(scope.getProperties(name));
091                }
092                if (descriptor == null) return Collections.emptyList();
093                return Collections.singleton(descriptor);
094            }
095    
096            @NotNull
097            @Override
098            public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiverType, Name name) {
099                return receiverType.getMemberScope().getProperties(name);
100            }
101    
102            @NotNull
103            @Override
104            public Collection<VariableDescriptor> getNonMembersByName(JetScope scope, Name name) {
105                Collection<VariableDescriptor> result = Sets.newLinkedHashSet();
106    
107                VariableDescriptor localVariable = scope.getLocalVariable(name);
108                if (localVariable != null) {
109                    result.add(localVariable);
110                }
111                result.addAll(scope.getProperties(name));
112                return result;
113            }
114    
115            @Override
116            public String toString() {
117                return "VARIABLES";
118            }
119        }
120    
121        private static class PropertyCollector implements CallableDescriptorCollector<VariableDescriptor> {
122            private static Collection<VariableDescriptor> filterProperties(Collection<? extends VariableDescriptor> variableDescriptors) {
123                ArrayList<VariableDescriptor> properties = Lists.newArrayList();
124                for (VariableDescriptor descriptor : variableDescriptors) {
125                    if (descriptor instanceof PropertyDescriptor) {
126                        properties.add(descriptor);
127                    }
128                }
129                return properties;
130            }
131    
132            @NotNull
133            @Override
134            public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, Name name) {
135                return filterProperties(VARIABLES.getNonExtensionsByName(scope, name));
136            }
137    
138            @NotNull
139            @Override
140            public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiver, Name name) {
141                return filterProperties(VARIABLES.getMembersByName(receiver, name));
142            }
143    
144            @NotNull
145            @Override
146            public Collection<VariableDescriptor> getNonMembersByName(JetScope scope, Name name) {
147                return filterProperties(VARIABLES.getNonMembersByName(scope, name));
148            }
149    
150            @Override
151            public String toString() {
152                return "PROPERTIES";
153            }
154        }
155    
156        private CallableDescriptorCollectors() {
157        }
158    }