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 }