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