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.lazy; 018 019 import com.google.common.collect.Lists; 020 import com.intellij.openapi.project.Project; 021 import com.intellij.util.Function; 022 import com.intellij.util.containers.ContainerUtil; 023 import kotlin.jvm.functions.Function1; 024 import org.jetbrains.annotations.NotNull; 025 import org.jetbrains.annotations.Nullable; 026 import org.jetbrains.annotations.ReadOnly; 027 import org.jetbrains.kotlin.context.GlobalContext; 028 import org.jetbrains.kotlin.descriptors.*; 029 import org.jetbrains.kotlin.descriptors.annotations.Annotations; 030 import org.jetbrains.kotlin.incremental.components.LookupLocation; 031 import org.jetbrains.kotlin.incremental.components.LookupTracker; 032 import org.jetbrains.kotlin.incremental.components.NoLookupLocation; 033 import org.jetbrains.kotlin.name.FqName; 034 import org.jetbrains.kotlin.name.Name; 035 import org.jetbrains.kotlin.psi.*; 036 import org.jetbrains.kotlin.resolve.*; 037 import org.jetbrains.kotlin.resolve.lazy.data.JetClassLikeInfo; 038 import org.jetbrains.kotlin.resolve.lazy.data.JetScriptInfo; 039 import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory; 040 import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider; 041 import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotations; 042 import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationsContextImpl; 043 import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor; 044 import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor; 045 import org.jetbrains.kotlin.resolve.scopes.JetScope; 046 import org.jetbrains.kotlin.storage.*; 047 048 import javax.inject.Inject; 049 import java.util.Collection; 050 import java.util.Collections; 051 import java.util.List; 052 053 public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { 054 private final LazyResolveStorageManager storageManager; 055 private final ExceptionTracker exceptionTracker; 056 057 private final ModuleDescriptor module; 058 059 private final BindingTrace trace; 060 private final DeclarationProviderFactory declarationProviderFactory; 061 062 private final MemoizedFunctionToNullable<FqName, LazyPackageDescriptor> packages; 063 private final PackageFragmentProvider packageFragmentProvider; 064 065 private final MemoizedFunctionToNotNull<JetScript, LazyScriptDescriptor> scriptDescriptors; 066 067 private final MemoizedFunctionToNotNull<JetFile, LazyAnnotations> fileAnnotations; 068 private final MemoizedFunctionToNotNull<JetFile, LazyAnnotations> danglingAnnotations; 069 070 private JetImportsFactory jetImportFactory; 071 private AnnotationResolver annotationResolve; 072 private DescriptorResolver descriptorResolver; 073 private FunctionDescriptorResolver functionDescriptorResolver; 074 private TypeResolver typeResolver; 075 private ScriptBodyResolver scriptBodyResolver; 076 private LazyDeclarationResolver lazyDeclarationResolver; 077 private FileScopeProvider fileScopeProvider; 078 private DeclarationScopeProvider declarationScopeProvider; 079 private LookupTracker lookupTracker; 080 private LocalDescriptorResolver localDescriptorResolver; 081 082 @Inject 083 public void setJetImportFactory(JetImportsFactory jetImportFactory) { 084 this.jetImportFactory = jetImportFactory; 085 } 086 087 @Inject 088 public void setAnnotationResolve(AnnotationResolver annotationResolve) { 089 this.annotationResolve = annotationResolve; 090 } 091 092 @Inject 093 public void setDescriptorResolver(DescriptorResolver descriptorResolver) { 094 this.descriptorResolver = descriptorResolver; 095 } 096 097 @Inject 098 public void setFunctionDescriptorResolver(FunctionDescriptorResolver functionDescriptorResolver) { 099 this.functionDescriptorResolver = functionDescriptorResolver; 100 } 101 102 @Inject 103 public void setTypeResolver(TypeResolver typeResolver) { 104 this.typeResolver = typeResolver; 105 } 106 107 @Inject 108 public void setScriptBodyResolver(ScriptBodyResolver scriptBodyResolver) { 109 this.scriptBodyResolver = scriptBodyResolver; 110 } 111 112 @Inject 113 public void setLazyDeclarationResolver(LazyDeclarationResolver lazyDeclarationResolver) { 114 this.lazyDeclarationResolver = lazyDeclarationResolver; 115 } 116 117 @Inject 118 public void setFileScopeProvider(@NotNull FileScopeProviderImpl fileScopeProvider) { 119 this.fileScopeProvider = fileScopeProvider; 120 } 121 122 @Inject 123 public void setDeclarationScopeProvider(@NotNull DeclarationScopeProviderImpl declarationScopeProvider) { 124 this.declarationScopeProvider = declarationScopeProvider; 125 } 126 127 @Inject 128 public void setLookupTracker(@NotNull LookupTracker lookupTracker) { 129 this.lookupTracker = lookupTracker; 130 } 131 132 // Only calls from injectors expected 133 @Deprecated 134 public ResolveSession( 135 @NotNull Project project, 136 @NotNull GlobalContext globalContext, 137 @NotNull ModuleDescriptor rootDescriptor, 138 @NotNull DeclarationProviderFactory declarationProviderFactory, 139 @NotNull BindingTrace delegationTrace 140 ) { 141 LockBasedLazyResolveStorageManager lockBasedLazyResolveStorageManager = 142 new LockBasedLazyResolveStorageManager(globalContext.getStorageManager()); 143 144 this.storageManager = lockBasedLazyResolveStorageManager; 145 this.exceptionTracker = globalContext.getExceptionTracker(); 146 this.trace = lockBasedLazyResolveStorageManager.createSafeTrace(delegationTrace); 147 this.module = rootDescriptor; 148 149 this.packages = 150 storageManager.createMemoizedFunctionWithNullableValues(new Function1<FqName, LazyPackageDescriptor>() { 151 @Override 152 @Nullable 153 public LazyPackageDescriptor invoke(FqName fqName) { 154 return createPackage(fqName); 155 } 156 }); 157 158 this.declarationProviderFactory = declarationProviderFactory; 159 160 this.packageFragmentProvider = new PackageFragmentProvider() { 161 @NotNull 162 @Override 163 public List<PackageFragmentDescriptor> getPackageFragments(@NotNull FqName fqName) { 164 return ContainerUtil.<PackageFragmentDescriptor>createMaybeSingletonList(getPackageFragment(fqName)); 165 } 166 167 @NotNull 168 @Override 169 public Collection<FqName> getSubPackagesOf( 170 @NotNull FqName fqName, @NotNull Function1<? super Name, ? extends Boolean> nameFilter 171 ) { 172 LazyPackageDescriptor packageDescriptor = getPackageFragment(fqName); 173 if (packageDescriptor == null) { 174 return Collections.emptyList(); 175 } 176 return packageDescriptor.getDeclarationProvider().getAllDeclaredSubPackages(nameFilter); 177 } 178 }; 179 180 this.scriptDescriptors = storageManager.createMemoizedFunction( 181 new Function1<JetScript, LazyScriptDescriptor>() { 182 @Override 183 public LazyScriptDescriptor invoke(JetScript script) { 184 return new LazyScriptDescriptor( 185 ResolveSession.this, 186 scriptBodyResolver, 187 script, 188 ScriptPriorities.getScriptPriority(script) 189 ); 190 } 191 } 192 ); 193 194 fileAnnotations = storageManager.createMemoizedFunction(new Function1<JetFile, LazyAnnotations>() { 195 @Override 196 public LazyAnnotations invoke(JetFile file) { 197 return createAnnotations(file, file.getAnnotationEntries()); 198 } 199 }); 200 201 danglingAnnotations = storageManager.createMemoizedFunction(new Function1<JetFile, LazyAnnotations>() { 202 @Override 203 public LazyAnnotations invoke(JetFile file) { 204 return createAnnotations(file, file.getDanglingAnnotations()); 205 } 206 }); 207 } 208 209 private LazyAnnotations createAnnotations(JetFile file, List<JetAnnotationEntry> annotationEntries) { 210 LazyFileScope scope = fileScopeProvider.getFileScope(file); 211 LazyAnnotationsContextImpl lazyAnnotationContext = 212 new LazyAnnotationsContextImpl(annotationResolve, storageManager, trace, scope); 213 return new LazyAnnotations(lazyAnnotationContext, annotationEntries); 214 } 215 216 @Override 217 @NotNull 218 public PackageFragmentProvider getPackageFragmentProvider() { 219 return packageFragmentProvider; 220 } 221 222 @Override 223 @Nullable 224 public LazyPackageDescriptor getPackageFragment(@NotNull FqName fqName) { 225 return packages.invoke(fqName); 226 } 227 228 @Nullable 229 private LazyPackageDescriptor createPackage(FqName fqName) { 230 PackageMemberDeclarationProvider provider = declarationProviderFactory.getPackageMemberDeclarationProvider(fqName); 231 if (provider == null) { 232 return null; 233 } 234 return new LazyPackageDescriptor(module, fqName, this, provider); 235 } 236 237 @NotNull 238 @Override 239 public ModuleDescriptor getModuleDescriptor() { 240 return module; 241 } 242 243 @NotNull 244 @Override 245 public LazyResolveStorageManager getStorageManager() { 246 return storageManager; 247 } 248 249 @NotNull 250 public ExceptionTracker getExceptionTracker() { 251 return exceptionTracker; 252 } 253 254 @Override 255 @NotNull 256 @ReadOnly 257 public Collection<ClassDescriptor> getTopLevelClassDescriptors(@NotNull FqName fqName, @NotNull final LookupLocation location) { 258 if (fqName.isRoot()) return Collections.emptyList(); 259 260 PackageMemberDeclarationProvider provider = declarationProviderFactory.getPackageMemberDeclarationProvider(fqName.parent()); 261 if (provider == null) return Collections.emptyList(); 262 263 return ContainerUtil.mapNotNull( 264 provider.getClassOrObjectDeclarations(fqName.shortName()), 265 new Function<JetClassLikeInfo, ClassDescriptor>() { 266 @Override 267 public ClassDescriptor fun(JetClassLikeInfo classLikeInfo) { 268 if (classLikeInfo instanceof JetScriptInfo) { 269 return getClassDescriptorForScript(((JetScriptInfo) classLikeInfo).getScript()); 270 } 271 JetClassOrObject classOrObject = classLikeInfo.getCorrespondingClassOrObject(); 272 if (classOrObject == null) return null; 273 return getClassDescriptor(classOrObject, location); 274 } 275 } 276 ); 277 } 278 279 @Override 280 @NotNull 281 public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject, @NotNull LookupLocation location) { 282 return lazyDeclarationResolver.getClassDescriptor(classOrObject, location); 283 } 284 285 @NotNull 286 public ClassDescriptor getClassDescriptorForScript(@NotNull JetScript script) { 287 JetScope memberScope = lazyDeclarationResolver.getMemberScopeDeclaredIn(script, NoLookupLocation.FOR_SCRIPT); 288 FqName fqName = ScriptNameUtil.classNameForScript(script); 289 ClassifierDescriptor classifier = memberScope.getClassifier(fqName.shortName(), NoLookupLocation.FOR_SCRIPT); 290 assert classifier != null : "No descriptor for " + fqName + " in file " + script.getContainingFile(); 291 return (ClassDescriptor) classifier; 292 } 293 294 @Override 295 @NotNull 296 public ScriptDescriptor getScriptDescriptor(@NotNull JetScript script) { 297 return scriptDescriptors.invoke(script); 298 } 299 300 @Override 301 @NotNull 302 public BindingContext getBindingContext() { 303 return trace.getBindingContext(); 304 } 305 306 @Override 307 @NotNull 308 public BindingTrace getTrace() { 309 return trace; 310 } 311 312 @Override 313 @NotNull 314 public DeclarationProviderFactory getDeclarationProviderFactory() { 315 return declarationProviderFactory; 316 } 317 318 @Override 319 @NotNull 320 public DeclarationDescriptor resolveToDescriptor(@NotNull JetDeclaration declaration) { 321 if (!JetPsiUtil.isLocal(declaration)) { 322 return lazyDeclarationResolver.resolveToDescriptor(declaration); 323 } 324 return localDescriptorResolver.resolveLocalDeclaration(declaration); 325 } 326 327 @NotNull 328 public Annotations getFileAnnotations(@NotNull JetFile file) { 329 return fileAnnotations.invoke(file); 330 } 331 332 @NotNull 333 public Annotations getDanglingAnnotations(@NotNull JetFile file) { 334 return danglingAnnotations.invoke(file); 335 } 336 337 @NotNull 338 private List<LazyPackageDescriptor> getAllPackages() { 339 LazyPackageDescriptor rootPackage = getPackageFragment(FqName.ROOT); 340 assert rootPackage != null : "Root package must be initialized"; 341 342 return collectAllPackages(Lists.<LazyPackageDescriptor>newArrayList(), rootPackage); 343 } 344 345 @NotNull 346 private List<LazyPackageDescriptor> collectAllPackages( 347 @NotNull List<LazyPackageDescriptor> result, 348 @NotNull LazyPackageDescriptor current 349 ) { 350 result.add(current); 351 for (FqName subPackage : packageFragmentProvider.getSubPackagesOf(current.getFqName(), JetScope.ALL_NAME_FILTER)) { 352 LazyPackageDescriptor fragment = getPackageFragment(subPackage); 353 assert fragment != null : "Couldn't find fragment for " + subPackage; 354 collectAllPackages(result, fragment); 355 } 356 return result; 357 } 358 359 @Override 360 public void forceResolveAll() { 361 for (LazyPackageDescriptor lazyPackage : getAllPackages()) { 362 ForceResolveUtil.forceResolveAllContents(lazyPackage); 363 } 364 } 365 366 @NotNull 367 public JetImportsFactory getJetImportsFactory() { 368 return jetImportFactory; 369 } 370 371 @Override 372 @NotNull 373 public AnnotationResolver getAnnotationResolver() { 374 return annotationResolve; 375 } 376 377 @Override 378 @NotNull 379 public DescriptorResolver getDescriptorResolver() { 380 return descriptorResolver; 381 } 382 383 @Override 384 @NotNull 385 public TypeResolver getTypeResolver() { 386 return typeResolver; 387 } 388 389 @NotNull 390 @Override 391 public FunctionDescriptorResolver getFunctionDescriptorResolver() { 392 return functionDescriptorResolver; 393 } 394 395 @NotNull 396 @Override 397 public DeclarationScopeProvider getDeclarationScopeProvider() { 398 return declarationScopeProvider; 399 } 400 401 @Override 402 @NotNull 403 public FileScopeProvider getFileScopeProvider() { 404 return fileScopeProvider; 405 } 406 407 @NotNull 408 @Override 409 public LookupTracker getLookupTracker() { 410 return lookupTracker; 411 } 412 413 @Inject 414 public void setLocalDescriptorResolver(@NotNull LocalDescriptorResolver localDescriptorResolver) { 415 this.localDescriptorResolver = localDescriptorResolver; 416 } 417 }