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