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.java.scope;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.annotations.TestOnly;
022    import org.jetbrains.jet.lang.descriptors.*;
023    import org.jetbrains.jet.lang.resolve.java.resolver.JavaMemberResolver;
024    import org.jetbrains.jet.lang.resolve.java.resolver.ProgressChecker;
025    import org.jetbrains.jet.lang.resolve.name.Name;
026    import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl;
027    import org.jetbrains.jet.utils.Printer;
028    
029    import java.util.*;
030    
031    public abstract class JavaBaseScope extends JetScopeImpl {
032        @NotNull
033        protected final JavaMemberResolver memberResolver;
034        @NotNull
035        protected final MembersProvider membersProvider;
036        @NotNull
037        private final Map<Name, Set<FunctionDescriptor>> functionDescriptors = new HashMap<Name, Set<FunctionDescriptor>>();
038        @NotNull
039        private final Map<Name, Set<VariableDescriptor>> propertyDescriptors = new HashMap<Name, Set<VariableDescriptor>>();
040        @Nullable
041        private Collection<DeclarationDescriptor> allDescriptors = null;
042        @Nullable
043        private Set<ClassDescriptor> objectDescriptors = null;
044        @NotNull
045        protected final ClassOrNamespaceDescriptor descriptor;
046    
047        private Collection<ClassDescriptor> innerClasses = null;
048    
049    
050        protected JavaBaseScope(
051                @NotNull ClassOrNamespaceDescriptor descriptor,
052                @NotNull JavaMemberResolver memberResolver,
053                @NotNull MembersProvider membersProvider
054        ) {
055            this.memberResolver = memberResolver;
056            this.membersProvider = membersProvider;
057            this.descriptor = descriptor;
058        }
059    
060        @NotNull
061        @Override
062        public DeclarationDescriptor getContainingDeclaration() {
063            return descriptor;
064        }
065    
066        @NotNull
067        @Override
068        public Collection<VariableDescriptor> getProperties(@NotNull Name name) {
069            Set<VariableDescriptor> cached = propertyDescriptors.get(name);
070            if (cached != null) return cached;
071    
072            if (allDescriptorsComputed()) {
073                return Collections.emptySet();
074            }
075    
076            Set<VariableDescriptor> computedDescriptors = computePropertyDescriptors(name);
077            propertyDescriptors.put(name, computedDescriptors);
078            return computedDescriptors;
079        }
080    
081        @NotNull
082        private Set<VariableDescriptor> computePropertyDescriptors(@NotNull Name name) {
083            NamedMembers members = membersProvider.get(name);
084            if (members == null) {
085                return Collections.emptySet();
086            }
087            return memberResolver.resolveFieldGroup(members, descriptor);
088        }
089    
090        @NotNull
091        @Override
092        public Collection<FunctionDescriptor> getFunctions(@NotNull Name name) {
093            Set<FunctionDescriptor> cached = functionDescriptors.get(name);
094            if (cached != null) return cached;
095    
096            if (allDescriptorsComputed()) {
097                return Collections.emptySet();
098            }
099    
100            Set<FunctionDescriptor> computedDescriptors = computeFunctionDescriptor(name);
101            functionDescriptors.put(name, computedDescriptors);
102            return computedDescriptors;
103        }
104    
105        @NotNull
106        protected abstract Set<FunctionDescriptor> computeFunctionDescriptor(@NotNull Name name);
107    
108        @NotNull
109        @Override
110        public Collection<DeclarationDescriptor> getAllDescriptors() {
111            if (allDescriptorsComputed()) {
112                return allDescriptors;
113            }
114    
115            allDescriptors = computeAllDescriptors();
116    
117            return allDescriptors;
118        }
119    
120        private boolean allDescriptorsComputed() {
121            return allDescriptors != null;
122        }
123    
124        @NotNull
125        protected Collection<DeclarationDescriptor> computeAllDescriptors() {
126            Collection<DeclarationDescriptor> result = new HashSet<DeclarationDescriptor>();
127            result.addAll(computeFieldAndFunctionDescriptors());
128            result.addAll(filterObjects(getInnerClasses(), false));
129            return result;
130        }
131    
132        @NotNull
133        @Override
134        public Set<ClassDescriptor> getObjectDescriptors() {
135            if (objectDescriptors == null) {
136                objectDescriptors = new HashSet<ClassDescriptor>(filterObjects(getInnerClasses(), true));
137            }
138            return objectDescriptors;
139        }
140    
141        @NotNull
142        protected abstract Collection<ClassDescriptor> computeInnerClasses();
143    
144        @NotNull
145        private Collection<DeclarationDescriptor> computeFieldAndFunctionDescriptors() {
146            Collection<DeclarationDescriptor> result = new ArrayList<DeclarationDescriptor>();
147            for (NamedMembers members : membersProvider.allMembers()) {
148                Name name = members.getName();
149                ProgressChecker.getInstance().checkCanceled();
150                result.addAll(getFunctions(name));
151                ProgressChecker.getInstance().checkCanceled();
152                result.addAll(getProperties(name));
153            }
154            return result;
155        }
156    
157        @NotNull
158        protected Collection<ClassDescriptor> getInnerClasses() {
159            if (innerClasses == null) {
160                innerClasses = computeInnerClasses();
161            }
162            return innerClasses;
163        }
164    
165        @NotNull
166        private static Collection<ClassDescriptor> filterObjects(@NotNull Collection<ClassDescriptor> classes, boolean objects) {
167            List<ClassDescriptor> result = new ArrayList<ClassDescriptor>();
168            for (ClassDescriptor descriptor : classes) {
169                if (descriptor.getKind().isSingleton() == objects) {
170                    result.add(descriptor);
171                }
172            }
173            return result;
174        }
175    
176        @TestOnly
177        @Override
178        public void printScopeStructure(@NotNull Printer p) {
179            p.println(getClass().getSimpleName(), " {");
180            p.pushIndent();
181    
182            p.println("descriptor = ", descriptor);
183    
184            p.popIndent();
185            p.println("}");
186        }
187    }