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