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;
018    
019    import com.google.common.base.Function;
020    import com.google.common.base.Functions;
021    import com.google.common.collect.Maps;
022    import com.intellij.psi.PsiElement;
023    import com.intellij.psi.PsiFile;
024    import org.jetbrains.annotations.NotNull;
025    import org.jetbrains.jet.lang.descriptors.*;
026    import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
027    import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptorLite;
028    import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl;
029    import org.jetbrains.jet.lang.psi.*;
030    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
031    import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
032    
033    import javax.inject.Inject;
034    import java.io.PrintStream;
035    import java.util.Collection;
036    import java.util.List;
037    import java.util.Map;
038    
039    public class TopDownAnalysisContext implements BodiesResolveContext {
040    
041        private final Map<JetClass, MutableClassDescriptor> classes = Maps.newLinkedHashMap();
042        private final Map<JetObjectDeclaration, MutableClassDescriptor> objects = Maps.newLinkedHashMap();
043        protected final Map<JetFile, NamespaceDescriptorImpl> namespaceDescriptors = Maps.newHashMap();
044        private List<MutableClassDescriptorLite> classesTopologicalOrder = null;
045    
046        private final Map<JetDeclaration, JetScope> declaringScopes = Maps.newHashMap();
047        private final Map<JetNamedFunction, SimpleFunctionDescriptor> functions = Maps.newLinkedHashMap();
048        private final Map<JetProperty, PropertyDescriptor> properties = Maps.newLinkedHashMap();
049        private final Map<JetParameter, PropertyDescriptor> primaryConstructorParameterProperties = Maps.newHashMap();
050        private Map<JetDeclaration, CallableMemberDescriptor> members = null;
051    
052        // File scopes - package scope extended with imports
053        protected final Map<JetFile, WritableScope> namespaceScopes = Maps.newHashMap();
054    
055        public final Map<JetDeclarationContainer, DeclarationDescriptor> forDeferredResolver = Maps.newHashMap();
056    
057        public final Map<JetDeclarationContainer, JetScope> normalScope = Maps.newHashMap();
058    
059        private final Map<JetScript, ScriptDescriptor> scripts = Maps.newLinkedHashMap();
060        private final Map<JetScript, WritableScope> scriptScopes = Maps.newHashMap();
061    
062        private StringBuilder debugOutput;
063    
064    
065        private TopDownAnalysisParameters topDownAnalysisParameters;
066    
067        @Override
068        @Inject
069        public void setTopDownAnalysisParameters(TopDownAnalysisParameters topDownAnalysisParameters) {
070            this.topDownAnalysisParameters = topDownAnalysisParameters;
071        }
072    
073        public TopDownAnalysisParameters getTopDownAnalysisParameters() {
074            return topDownAnalysisParameters;
075        }
076    
077        public void debug(Object message) {
078            if (debugOutput != null) {
079                debugOutput.append(message).append("\n");
080            }
081        }
082    
083        @SuppressWarnings("UnusedDeclaration")
084        /*package*/ void enableDebugOutput() {
085            if (debugOutput == null) {
086                debugOutput = new StringBuilder();
087            }
088        }
089        
090        /*package*/ void printDebugOutput(PrintStream out) {
091            if (debugOutput != null) {
092                out.print(debugOutput);
093            }
094        }
095    
096        @Override
097        public boolean completeAnalysisNeeded(@NotNull PsiElement element) {
098            PsiFile containingFile = element.getContainingFile();
099            boolean result = containingFile != null && topDownAnalysisParameters.getAnalyzeCompletely().apply(containingFile);
100            if (!result) {
101                debug(containingFile);
102            }
103            return result;
104        }
105    
106        @Override
107        public Map<JetClass, MutableClassDescriptor> getClasses() {
108            return classes;
109        }
110    
111        @Override
112        public Map<JetObjectDeclaration, MutableClassDescriptor> getObjects() {
113            return objects;
114        }
115    
116        public Map<JetFile, WritableScope> getNamespaceScopes() {
117            return namespaceScopes;
118        }
119    
120        public Map<JetFile, NamespaceDescriptorImpl> getNamespaceDescriptors() {
121            return namespaceDescriptors;
122        }
123    
124        @Override
125        public Collection<JetFile> getFiles() {
126            return namespaceDescriptors.keySet();
127        }
128    
129        @Override
130        @NotNull
131        public Map<JetScript, ScriptDescriptor> getScripts() {
132            return scripts;
133        }
134    
135        @Override
136        @NotNull
137        public Map<JetScript, WritableScope> getScriptScopes() {
138            return scriptScopes;
139        }
140    
141        public Map<JetParameter, PropertyDescriptor> getPrimaryConstructorParameterProperties() {
142            return primaryConstructorParameterProperties;
143        }
144    
145        @Override
146        public Map<JetProperty, PropertyDescriptor> getProperties() {
147            return properties;
148        }
149    
150        @Override
151        public Function<JetDeclaration, JetScope> getDeclaringScopes() {
152            return Functions.forMap(declaringScopes);
153        }
154    
155        public void registerDeclaringScope(@NotNull JetDeclaration declaration, @NotNull JetScope scope) {
156            declaringScopes.put(declaration, scope);
157        }
158    
159        @Override
160        public Map<JetNamedFunction, SimpleFunctionDescriptor> getFunctions() {
161            return functions;
162        }
163    
164        public Map<JetDeclaration, CallableMemberDescriptor> getMembers() {
165            if (members == null) {
166                members = Maps.newHashMap();
167                members.putAll(functions);
168                members.putAll(properties);
169                members.putAll(primaryConstructorParameterProperties);
170            }
171            return members;
172        }
173    
174        @NotNull
175        public List<MutableClassDescriptorLite> getClassesTopologicalOrder() {
176            return classesTopologicalOrder;
177        }
178    
179        public void setClassesTopologicalOrder(@NotNull List<MutableClassDescriptorLite> classesTopologicalOrder) {
180            this.classesTopologicalOrder = classesTopologicalOrder;
181        }
182    }