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.scopes;
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.resolve.name.Name;
023    
024    import java.util.*;
025    
026    public class JetScopeSelectorUtil {
027        private JetScopeSelectorUtil() {
028        }
029    
030        public interface ScopeByNameSelector<D extends DeclarationDescriptor> {
031            @Nullable
032            D get(@NotNull JetScope scope, @NotNull Name name);
033        }
034    
035        public interface ScopeByNameMultiSelector<D extends DeclarationDescriptor> {
036            @NotNull
037            Collection<D> get(JetScope scope, Name name);
038        }
039    
040        public interface ScopeDescriptorSelector<D extends DeclarationDescriptor> {
041            @NotNull
042            Collection<D> get(JetScope scope);
043        }
044    
045        @NotNull
046        public static <D extends DeclarationDescriptor> Collection<D> collect(Collection<JetScope> scopes, ScopeByNameMultiSelector<D> selector, Name name) {
047            Set<D> descriptors = new HashSet<D>();
048    
049            for (JetScope scope : scopes) {
050                descriptors.addAll(selector.get(scope, name));
051            }
052    
053            return descriptors;
054        }
055    
056        @NotNull
057        public static <D extends DeclarationDescriptor> Collection<D> collect(Collection<JetScope> scopes, ScopeDescriptorSelector<D> selector) {
058            Set<D> descriptors = new HashSet<D>();
059    
060            for (JetScope scope : scopes) {
061                descriptors.addAll(selector.get(scope));
062            }
063    
064            return descriptors;
065        }
066    
067        public static final ScopeByNameSelector<ClassifierDescriptor> CLASSIFIER_DESCRIPTOR_SCOPE_SELECTOR =
068                new ScopeByNameSelector<ClassifierDescriptor>() {
069                    @Nullable
070                    @Override
071                    public ClassifierDescriptor get(@NotNull JetScope scope, @NotNull Name name) {
072                        return scope.getClassifier(name);
073                    }
074                };
075    
076        public static final ScopeByNameSelector<PackageViewDescriptor> PACKAGE_SCOPE_SELECTOR =
077                new ScopeByNameSelector<PackageViewDescriptor>() {
078                    @Nullable
079                    @Override
080                    public PackageViewDescriptor get(@NotNull JetScope scope, @NotNull Name name) {
081                        return scope.getPackage(name);
082                    }
083                };
084    
085        public static final ScopeByNameSelector<VariableDescriptor> VARIABLE_DESCRIPTOR_SCOPE_SELECTOR =
086                new ScopeByNameSelector<VariableDescriptor>() {
087                    @Nullable
088                    @Override
089                    public VariableDescriptor get(@NotNull JetScope scope, @NotNull Name name) {
090                        return scope.getLocalVariable(name);
091                    }
092                };
093    
094        public static final ScopeByNameMultiSelector<FunctionDescriptor> NAMED_FUNCTION_SCOPE_SELECTOR =
095                new ScopeByNameMultiSelector<FunctionDescriptor>() {
096                    @NotNull
097                    @Override
098                    public Collection<FunctionDescriptor> get(@NotNull JetScope scope, @NotNull Name name) {
099                        return scope.getFunctions(name);
100                    }
101                };
102    
103        public static final ScopeByNameMultiSelector<VariableDescriptor> NAMED_PROPERTIES_SCOPE_SELECTOR =
104                new ScopeByNameMultiSelector<VariableDescriptor>() {
105                    @NotNull
106                    @Override
107                    public Collection<VariableDescriptor> get(@NotNull JetScope scope, @NotNull Name name) {
108                        return scope.getProperties(name);
109                    }
110                };
111    
112        public static final ScopeDescriptorSelector<DeclarationDescriptor> ALL_DESCRIPTORS_SCOPE_SELECTOR =
113                new ScopeDescriptorSelector<DeclarationDescriptor>() {
114                    @NotNull
115                    @Override
116                    public Collection<DeclarationDescriptor> get(@NotNull JetScope scope) {
117                        return scope.getAllDescriptors();
118                    }
119                };
120    
121        @Nullable
122        public static <D extends DeclarationDescriptor> D getFirstMatch(
123                @NotNull JetScope[] scopes,
124                @NotNull Name name,
125                @NotNull ScopeByNameSelector<D> descriptorSelector
126        ) {
127            for (JetScope scope : scopes) {
128                D descriptor = descriptorSelector.get(scope, name);
129    
130                if (descriptor != null) {
131                    return descriptor;
132                }
133            }
134    
135            return null;
136        }
137    
138        @NotNull
139        public static <D extends DeclarationDescriptor> Set<D> getFromAllScopes(
140                @NotNull JetScope[] scopes,
141                @NotNull Name name,
142                @NotNull ScopeByNameMultiSelector<D> descriptorsSelector
143        ) {
144            if (scopes.length == 0) return Collections.emptySet();
145    
146            Set<D> descriptors = new LinkedHashSet<D>();
147            for (JetScope jetScope : scopes) {
148                descriptors.addAll(descriptorsSelector.get(jetScope, name));
149            }
150    
151            return descriptors;
152        }
153    }