001 /* 002 * Copyright 2010-2015 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.kotlin.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.kotlin.descriptors.*; 028 import org.jetbrains.kotlin.descriptors.impl.MutableClassDescriptor; 029 import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor; 030 import org.jetbrains.kotlin.psi.*; 031 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; 032 import org.jetbrains.kotlin.resolve.scopes.JetScope; 033 import org.jetbrains.kotlin.resolve.scopes.WritableScope; 034 import org.jetbrains.kotlin.storage.ExceptionTracker; 035 import org.jetbrains.kotlin.storage.StorageManager; 036 037 import java.io.PrintStream; 038 import java.util.*; 039 040 public class TopDownAnalysisContext implements BodiesResolveContext { 041 042 private final DataFlowInfo outerDataFlowInfo; 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<JetCallableDeclaration, 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, @NotNull DataFlowInfo outerDataFlowInfo) { 070 this.topDownAnalysisParameters = topDownAnalysisParameters; 071 this.outerDataFlowInfo = outerDataFlowInfo; 072 } 073 074 @Override 075 @NotNull 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<JetClassOrObject, ClassDescriptorWithResolutionScopes> getDeclaredClasses() { 111 return classes; 112 } 113 114 @Override 115 public Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() { 116 return anonymousInitializers; 117 } 118 119 public Map<JetFile, WritableScope> getFileScopes() { 120 return fileScopes; 121 } 122 123 public Map<JetFile, MutablePackageFragmentDescriptor> getPackageFragments() { 124 return packageFragments; 125 } 126 127 @NotNull 128 @Override 129 public StorageManager getStorageManager() { 130 return topDownAnalysisParameters.getStorageManager(); 131 } 132 133 @NotNull 134 @Override 135 public ExceptionTracker getExceptionTracker() { 136 return topDownAnalysisParameters.getExceptionTracker(); 137 } 138 139 @Override 140 public Collection<JetFile> getFiles() { 141 return files; 142 } 143 144 public void addFile(@NotNull JetFile file) { 145 files.add(file); 146 } 147 148 @Override 149 @NotNull 150 public Map<JetScript, ScriptDescriptor> getScripts() { 151 return scripts; 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 @NotNull 178 public Map<JetCallableDeclaration, CallableMemberDescriptor> getMembers() { 179 if (members == null) { 180 members = Maps.newLinkedHashMap(); 181 members.putAll(functions); 182 members.putAll(properties); 183 members.putAll(primaryConstructorParameterProperties); 184 } 185 return members; 186 } 187 188 @NotNull 189 public List<MutableClassDescriptor> getClassesTopologicalOrder() { 190 return classesTopologicalOrder; 191 } 192 193 public void setClassesTopologicalOrder(@NotNull List<MutableClassDescriptor> classesTopologicalOrder) { 194 this.classesTopologicalOrder = classesTopologicalOrder; 195 } 196 197 @Override 198 @NotNull 199 public DataFlowInfo getOuterDataFlowInfo() { 200 return outerDataFlowInfo; 201 } 202 203 @NotNull 204 public Collection<ClassDescriptorWithResolutionScopes> getAllClasses() { 205 // SCRIPT: all classes are declared classes + script classes 206 Collection<ClassDescriptorWithResolutionScopes> scriptClasses = KotlinPackage.map( 207 getScripts().values(), 208 new Function1<ScriptDescriptor, ClassDescriptorWithResolutionScopes>() { 209 @Override 210 public ClassDescriptorWithResolutionScopes invoke(ScriptDescriptor scriptDescriptor) { 211 return (ClassDescriptorWithResolutionScopes) scriptDescriptor.getClassDescriptor(); 212 } 213 } 214 ); 215 return KotlinPackage.plus(getDeclaredClasses().values(), scriptClasses); 216 } 217 }