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