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 kotlin.Function1;
025 import kotlin.KotlinPackage;
026 import org.jetbrains.annotations.NotNull;
027 import org.jetbrains.jet.lang.descriptors.*;
028 import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
029 import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor;
030 import org.jetbrains.jet.lang.psi.*;
031 import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
032 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
033 import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
034 import org.jetbrains.jet.storage.ExceptionTracker;
035 import org.jetbrains.jet.storage.StorageManager;
036
037 import java.io.PrintStream;
038 import java.util.*;
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 private final Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> anonymousInitializers = Maps.newLinkedHashMap();
046 protected final Map<JetFile, MutablePackageFragmentDescriptor> packageFragments = Maps.newHashMap();
047 protected final Set<JetFile> files = new LinkedHashSet<JetFile>();
048 private List<MutableClassDescriptor> classesTopologicalOrder = null;
049
050 private final Map<JetDeclaration, JetScope> declaringScopes = Maps.newHashMap();
051 private final Map<JetNamedFunction, SimpleFunctionDescriptor> functions = Maps.newLinkedHashMap();
052 private final Map<JetProperty, PropertyDescriptor> properties = Maps.newLinkedHashMap();
053 private final Map<JetParameter, PropertyDescriptor> primaryConstructorParameterProperties = Maps.newHashMap();
054 private Map<JetDeclaration, CallableMemberDescriptor> members = null;
055
056 // File scopes - package scope extended with imports
057 protected final Map<JetFile, WritableScope> fileScopes = Maps.newHashMap();
058
059 public final Map<JetDeclarationContainer, DeclarationDescriptor> forDeferredResolver = Maps.newHashMap();
060
061 public final Map<JetDeclarationContainer, JetScope> normalScope = Maps.newHashMap();
062
063 private final Map<JetScript, ScriptDescriptor> scripts = Maps.newLinkedHashMap();
064
065 private final TopDownAnalysisParameters topDownAnalysisParameters;
066
067 private StringBuilder debugOutput;
068
069 public TopDownAnalysisContext(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) {
070 this.topDownAnalysisParameters = topDownAnalysisParameters;
071 }
072
073 @Override
074 @NotNull
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, ClassDescriptorWithResolutionScopes> getDeclaredClasses() {
110 return classes;
111 }
112
113 @Override
114 public Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() {
115 return anonymousInitializers;
116 }
117
118 public Map<JetFile, WritableScope> getFileScopes() {
119 return fileScopes;
120 }
121
122 public Map<JetFile, MutablePackageFragmentDescriptor> getPackageFragments() {
123 return packageFragments;
124 }
125
126 @NotNull
127 @Override
128 public StorageManager getStorageManager() {
129 return topDownAnalysisParameters.getStorageManager();
130 }
131
132 @NotNull
133 @Override
134 public ExceptionTracker getExceptionTracker() {
135 return topDownAnalysisParameters.getExceptionTracker();
136 }
137
138 @Override
139 public Collection<JetFile> getFiles() {
140 return files;
141 }
142
143 public void addFile(@NotNull JetFile file) {
144 files.add(file);
145 }
146
147 @Override
148 @NotNull
149 public Map<JetScript, ScriptDescriptor> getScripts() {
150 return scripts;
151 }
152
153 public Map<JetParameter, PropertyDescriptor> getPrimaryConstructorParameterProperties() {
154 return primaryConstructorParameterProperties;
155 }
156
157 @Override
158 public Map<JetProperty, PropertyDescriptor> getProperties() {
159 return properties;
160 }
161
162 @Override
163 public Function<JetDeclaration, JetScope> getDeclaringScopes() {
164 return Functions.forMap(declaringScopes);
165 }
166
167 public void registerDeclaringScope(@NotNull JetDeclaration declaration, @NotNull JetScope scope) {
168 declaringScopes.put(declaration, scope);
169 }
170
171 @Override
172 public Map<JetNamedFunction, SimpleFunctionDescriptor> getFunctions() {
173 return functions;
174 }
175
176 public Map<JetDeclaration, CallableMemberDescriptor> getMembers() {
177 if (members == null) {
178 members = Maps.newHashMap();
179 members.putAll(functions);
180 members.putAll(properties);
181 members.putAll(primaryConstructorParameterProperties);
182 }
183 return members;
184 }
185
186 @NotNull
187 public List<MutableClassDescriptor> getClassesTopologicalOrder() {
188 return classesTopologicalOrder;
189 }
190
191 public void setClassesTopologicalOrder(@NotNull List<MutableClassDescriptor> classesTopologicalOrder) {
192 this.classesTopologicalOrder = classesTopologicalOrder;
193 }
194
195 @Override
196 @NotNull
197 public DataFlowInfo getOuterDataFlowInfo() {
198 return outerDataFlowInfo;
199 }
200
201 public void setOuterDataFlowInfo(@NotNull DataFlowInfo outerDataFlowInfo) {
202 this.outerDataFlowInfo = outerDataFlowInfo;
203 }
204
205 @NotNull
206 public Collection<ClassDescriptorWithResolutionScopes> getAllClasses() {
207 // SCRIPT: all classes are declared classes + script classes
208 Collection<ClassDescriptorWithResolutionScopes> scriptClasses = KotlinPackage.map(
209 getScripts().values(),
210 new Function1<ScriptDescriptor, ClassDescriptorWithResolutionScopes>() {
211 @Override
212 public ClassDescriptorWithResolutionScopes invoke(ScriptDescriptor scriptDescriptor) {
213 return (ClassDescriptorWithResolutionScopes) scriptDescriptor.getClassDescriptor();
214 }
215 }
216 );
217 return KotlinPackage.plus(getDeclaredClasses().values(), scriptClasses);
218 }
219 }