From 6285efe32d0091d8c460b608e1c622d82f6045b1 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 22 Jan 2015 19:56:09 +0300 Subject: [PATCH] LazyDeclarationResolver extracted from ResolveSession --- .../di/InjectorForLazyResolveWithJava.java | 25 +- .../kotlin/di/InjectorForReplWithJava.java | 19 +- .../di/InjectorForTopDownAnalyzerForJvm.java | 25 +- .../kotlin/di/InjectorForLazyResolve.java | 25 +- .../InjectorForLazyTopDownAnalyzerBasic.java | 25 +- .../lazy/DeclarationScopeProviderImpl.java | 10 +- .../resolve/lazy/KotlinCodeAnalyzer.java | 15 +- .../resolve/lazy/LazyDeclarationResolver.java | 251 ++++++++++++++++++ .../kotlin/resolve/lazy/ResolveSession.java | 209 ++------------- .../lazy/TopLevelDescriptorProvider.kt | 31 +++ .../generators/injectors/GenerateInjectors.kt | 2 + .../di/InjectorForTopDownAnalyzerForJs.java | 25 +- 12 files changed, 410 insertions(+), 252 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyDeclarationResolver.java create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/TopLevelDescriptorProvider.kt diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/di/InjectorForLazyResolveWithJava.java b/compiler/frontend.java/src/org/jetbrains/kotlin/di/InjectorForLazyResolveWithJava.java index 695d5c295a9..a1c425553e8 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/di/InjectorForLazyResolveWithJava.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/di/InjectorForLazyResolveWithJava.java @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap; import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory; import org.jetbrains.kotlin.resolve.lazy.ResolveSession; +import org.jetbrains.kotlin.resolve.lazy.ScopeProvider; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver; import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver; @@ -63,10 +64,10 @@ import org.jetbrains.kotlin.resolve.calls.CallCompleter; import org.jetbrains.kotlin.resolve.calls.CandidateResolver; import org.jetbrains.kotlin.resolve.calls.tasks.TaskPrioritizer; import org.jetbrains.kotlin.psi.JetImportsFactory; -import org.jetbrains.kotlin.resolve.lazy.ScopeProvider; -import org.jetbrains.kotlin.resolve.lazy.ScopeProvider.AdditionalFileScopeProvider; +import org.jetbrains.kotlin.resolve.lazy.LazyDeclarationResolver; import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProviderImpl; import org.jetbrains.kotlin.resolve.ScriptBodyResolver; +import org.jetbrains.kotlin.resolve.lazy.ScopeProvider.AdditionalFileScopeProvider; import org.jetbrains.kotlin.load.java.lazy.LazyJavaPackageFragmentProvider; import org.jetbrains.kotlin.load.java.lazy.GlobalJavaResolverContext; import org.jetbrains.kotlin.load.kotlin.DeserializedDescriptorResolver; @@ -89,6 +90,7 @@ public class InjectorForLazyResolveWithJava { private final PlatformToKotlinClassMap platformToKotlinClassMap; private final DeclarationProviderFactory declarationProviderFactory; private final ResolveSession resolveSession; + private final ScopeProvider scopeProvider; private final GlobalSearchScope moduleContentScope; private final ModuleClassResolver moduleClassResolver; private final JavaDescriptorResolver javaDescriptorResolver; @@ -127,10 +129,10 @@ public class InjectorForLazyResolveWithJava { private final CandidateResolver candidateResolver; private final TaskPrioritizer taskPrioritizer; private final JetImportsFactory jetImportsFactory; - private final ScopeProvider scopeProvider; - private final AdditionalFileScopeProvider additionalFileScopeProvider; + private final LazyDeclarationResolver lazyDeclarationResolver; private final DeclarationScopeProviderImpl declarationScopeProvider; private final ScriptBodyResolver scriptBodyResolver; + private final AdditionalFileScopeProvider additionalFileScopeProvider; private final LazyJavaPackageFragmentProvider lazyJavaPackageFragmentProvider; private final GlobalJavaResolverContext globalJavaResolverContext; private final DeserializedDescriptorResolver deserializedDescriptorResolver; @@ -156,6 +158,7 @@ public class InjectorForLazyResolveWithJava { this.platformToKotlinClassMap = module.getPlatformToKotlinClassMap(); this.declarationProviderFactory = declarationProviderFactory; this.resolveSession = new ResolveSession(project, globalContext, module, declarationProviderFactory, bindingTrace); + this.scopeProvider = new ScopeProvider(getResolveSession()); this.moduleContentScope = moduleContentScope; this.moduleClassResolver = moduleClassResolver; this.javaClassFinder = new JavaClassFinderImpl(); @@ -197,10 +200,10 @@ public class InjectorForLazyResolveWithJava { this.callCompleter = new CallCompleter(argumentTypeResolver, candidateResolver); this.taskPrioritizer = new TaskPrioritizer(storageManager); this.jetImportsFactory = new JetImportsFactory(); - this.scopeProvider = new ScopeProvider(getResolveSession()); - this.additionalFileScopeProvider = new AdditionalFileScopeProvider(); - this.declarationScopeProvider = new DeclarationScopeProviderImpl(getResolveSession()); + this.lazyDeclarationResolver = new LazyDeclarationResolver(globalContext, bindingTrace); + this.declarationScopeProvider = new DeclarationScopeProviderImpl(lazyDeclarationResolver); this.scriptBodyResolver = new ScriptBodyResolver(); + this.additionalFileScopeProvider = new AdditionalFileScopeProvider(); this.javaClassDataFinder = new JavaClassDataFinder(virtualFileFinder, deserializedDescriptorResolver); this.binaryClassAnnotationAndConstantLoader = new BinaryClassAnnotationAndConstantLoaderImpl(module, storageManager, virtualFileFinder, traceBasedErrorReporter); this.deserializationComponentsForJava = new DeserializationComponentsForJava(storageManager, module, javaClassDataFinder, binaryClassAnnotationAndConstantLoader, lazyJavaPackageFragmentProvider); @@ -208,11 +211,15 @@ public class InjectorForLazyResolveWithJava { this.resolveSession.setAnnotationResolve(annotationResolver); this.resolveSession.setDescriptorResolver(descriptorResolver); this.resolveSession.setJetImportFactory(jetImportsFactory); + this.resolveSession.setLazyDeclarationResolver(lazyDeclarationResolver); this.resolveSession.setQualifiedExpressionResolver(qualifiedExpressionResolver); this.resolveSession.setScopeProvider(scopeProvider); this.resolveSession.setScriptBodyResolver(scriptBodyResolver); this.resolveSession.setTypeResolver(typeResolver); + scopeProvider.setAdditionalFileScopesProvider(additionalFileScopeProvider); + scopeProvider.setDeclarationScopeProvider(declarationScopeProvider); + javaClassFinder.setComponentPostConstruct(javaLazyAnalyzerPostConstruct); javaClassFinder.setProject(project); javaClassFinder.setScope(moduleContentScope); @@ -291,8 +298,8 @@ public class InjectorForLazyResolveWithJava { jetImportsFactory.setProject(project); - scopeProvider.setAdditionalFileScopesProvider(additionalFileScopeProvider); - scopeProvider.setDeclarationScopeProvider(declarationScopeProvider); + lazyDeclarationResolver.setDeclarationScopeProvider(declarationScopeProvider); + lazyDeclarationResolver.setTopLevelDescriptorProvider(resolveSession); declarationScopeProvider.setFileScopeProvider(scopeProvider); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/di/InjectorForReplWithJava.java b/compiler/frontend.java/src/org/jetbrains/kotlin/di/InjectorForReplWithJava.java index 5a1f705a41c..fc832176792 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/di/InjectorForReplWithJava.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/di/InjectorForReplWithJava.java @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap; import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory; import org.jetbrains.kotlin.resolve.lazy.ResolveSession; +import org.jetbrains.kotlin.resolve.lazy.ScopeProvider; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer; import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver; @@ -66,7 +67,7 @@ import org.jetbrains.kotlin.resolve.calls.CallCompleter; import org.jetbrains.kotlin.resolve.calls.CandidateResolver; import org.jetbrains.kotlin.resolve.calls.tasks.TaskPrioritizer; import org.jetbrains.kotlin.psi.JetImportsFactory; -import org.jetbrains.kotlin.resolve.lazy.ScopeProvider; +import org.jetbrains.kotlin.resolve.lazy.LazyDeclarationResolver; import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProviderImpl; import org.jetbrains.kotlin.resolve.ScriptBodyResolver; import org.jetbrains.kotlin.resolve.BodyResolver; @@ -100,6 +101,7 @@ public class InjectorForReplWithJava { private final PlatformToKotlinClassMap platformToKotlinClassMap; private final DeclarationProviderFactory declarationProviderFactory; private final ResolveSession resolveSession; + private final ScopeProvider scopeProvider; private final GlobalSearchScope moduleContentScope; private final LazyTopDownAnalyzer lazyTopDownAnalyzer; private final JavaDescriptorResolver javaDescriptorResolver; @@ -141,7 +143,7 @@ public class InjectorForReplWithJava { private final CandidateResolver candidateResolver; private final TaskPrioritizer taskPrioritizer; private final JetImportsFactory jetImportsFactory; - private final ScopeProvider scopeProvider; + private final LazyDeclarationResolver lazyDeclarationResolver; private final DeclarationScopeProviderImpl declarationScopeProvider; private final ScriptBodyResolver scriptBodyResolver; private final BodyResolver bodyResolver; @@ -178,6 +180,7 @@ public class InjectorForReplWithJava { this.platformToKotlinClassMap = module.getPlatformToKotlinClassMap(); this.declarationProviderFactory = declarationProviderFactory; this.resolveSession = new ResolveSession(project, globalContext, module, declarationProviderFactory, bindingTrace); + this.scopeProvider = new ScopeProvider(getResolveSession()); this.moduleContentScope = moduleContentScope; this.lazyTopDownAnalyzer = new LazyTopDownAnalyzer(); this.javaClassFinder = new JavaClassFinderImpl(); @@ -224,8 +227,8 @@ public class InjectorForReplWithJava { this.callCompleter = new CallCompleter(argumentTypeResolver, candidateResolver); this.taskPrioritizer = new TaskPrioritizer(storageManager); this.jetImportsFactory = new JetImportsFactory(); - this.scopeProvider = new ScopeProvider(getResolveSession()); - this.declarationScopeProvider = new DeclarationScopeProviderImpl(getResolveSession()); + this.lazyDeclarationResolver = new LazyDeclarationResolver(globalContext, bindingTrace); + this.declarationScopeProvider = new DeclarationScopeProviderImpl(lazyDeclarationResolver); this.scriptBodyResolver = new ScriptBodyResolver(); this.bodyResolver = new BodyResolver(); this.controlFlowAnalyzer = new ControlFlowAnalyzer(); @@ -241,11 +244,15 @@ public class InjectorForReplWithJava { this.resolveSession.setAnnotationResolve(annotationResolver); this.resolveSession.setDescriptorResolver(descriptorResolver); this.resolveSession.setJetImportFactory(jetImportsFactory); + this.resolveSession.setLazyDeclarationResolver(lazyDeclarationResolver); this.resolveSession.setQualifiedExpressionResolver(qualifiedExpressionResolver); this.resolveSession.setScopeProvider(scopeProvider); this.resolveSession.setScriptBodyResolver(scriptBodyResolver); this.resolveSession.setTypeResolver(typeResolver); + scopeProvider.setAdditionalFileScopesProvider(additionalFileScopeProvider); + scopeProvider.setDeclarationScopeProvider(declarationScopeProvider); + this.lazyTopDownAnalyzer.setBodyResolver(bodyResolver); this.lazyTopDownAnalyzer.setDeclarationResolver(declarationResolver); this.lazyTopDownAnalyzer.setKotlinCodeAnalyzer(resolveSession); @@ -335,8 +342,8 @@ public class InjectorForReplWithJava { jetImportsFactory.setProject(project); - scopeProvider.setAdditionalFileScopesProvider(additionalFileScopeProvider); - scopeProvider.setDeclarationScopeProvider(declarationScopeProvider); + lazyDeclarationResolver.setDeclarationScopeProvider(declarationScopeProvider); + lazyDeclarationResolver.setTopLevelDescriptorProvider(resolveSession); declarationScopeProvider.setFileScopeProvider(scopeProvider); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/di/InjectorForTopDownAnalyzerForJvm.java index 1c45686f4ea..6d39320e0e2 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/di/InjectorForTopDownAnalyzerForJvm.java @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap; import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory; import org.jetbrains.kotlin.resolve.lazy.ResolveSession; +import org.jetbrains.kotlin.resolve.lazy.ScopeProvider; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer; import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver; @@ -65,10 +66,10 @@ import org.jetbrains.kotlin.resolve.calls.CallCompleter; import org.jetbrains.kotlin.resolve.calls.CandidateResolver; import org.jetbrains.kotlin.resolve.calls.tasks.TaskPrioritizer; import org.jetbrains.kotlin.psi.JetImportsFactory; -import org.jetbrains.kotlin.resolve.lazy.ScopeProvider; -import org.jetbrains.kotlin.resolve.lazy.ScopeProvider.AdditionalFileScopeProvider; +import org.jetbrains.kotlin.resolve.lazy.LazyDeclarationResolver; import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProviderImpl; import org.jetbrains.kotlin.resolve.ScriptBodyResolver; +import org.jetbrains.kotlin.resolve.lazy.ScopeProvider.AdditionalFileScopeProvider; import org.jetbrains.kotlin.resolve.BodyResolver; import org.jetbrains.kotlin.resolve.ControlFlowAnalyzer; import org.jetbrains.kotlin.resolve.DeclarationsChecker; @@ -100,6 +101,7 @@ public class InjectorForTopDownAnalyzerForJvm { private final PlatformToKotlinClassMap platformToKotlinClassMap; private final DeclarationProviderFactory declarationProviderFactory; private final ResolveSession resolveSession; + private final ScopeProvider scopeProvider; private final GlobalSearchScope moduleContentScope; private final LazyTopDownAnalyzer lazyTopDownAnalyzer; private final JavaDescriptorResolver javaDescriptorResolver; @@ -140,10 +142,10 @@ public class InjectorForTopDownAnalyzerForJvm { private final CandidateResolver candidateResolver; private final TaskPrioritizer taskPrioritizer; private final JetImportsFactory jetImportsFactory; - private final ScopeProvider scopeProvider; - private final AdditionalFileScopeProvider additionalFileScopeProvider; + private final LazyDeclarationResolver lazyDeclarationResolver; private final DeclarationScopeProviderImpl declarationScopeProvider; private final ScriptBodyResolver scriptBodyResolver; + private final AdditionalFileScopeProvider additionalFileScopeProvider; private final BodyResolver bodyResolver; private final ControlFlowAnalyzer controlFlowAnalyzer; private final DeclarationsChecker declarationsChecker; @@ -177,6 +179,7 @@ public class InjectorForTopDownAnalyzerForJvm { this.platformToKotlinClassMap = module.getPlatformToKotlinClassMap(); this.declarationProviderFactory = declarationProviderFactory; this.resolveSession = new ResolveSession(project, globalContext, module, declarationProviderFactory, bindingTrace); + this.scopeProvider = new ScopeProvider(getResolveSession()); this.moduleContentScope = moduleContentScope; this.lazyTopDownAnalyzer = new LazyTopDownAnalyzer(); this.javaClassFinder = new JavaClassFinderImpl(); @@ -222,10 +225,10 @@ public class InjectorForTopDownAnalyzerForJvm { this.callCompleter = new CallCompleter(argumentTypeResolver, candidateResolver); this.taskPrioritizer = new TaskPrioritizer(storageManager); this.jetImportsFactory = new JetImportsFactory(); - this.scopeProvider = new ScopeProvider(getResolveSession()); - this.additionalFileScopeProvider = new AdditionalFileScopeProvider(); - this.declarationScopeProvider = new DeclarationScopeProviderImpl(getResolveSession()); + this.lazyDeclarationResolver = new LazyDeclarationResolver(globalContext, bindingTrace); + this.declarationScopeProvider = new DeclarationScopeProviderImpl(lazyDeclarationResolver); this.scriptBodyResolver = new ScriptBodyResolver(); + this.additionalFileScopeProvider = new AdditionalFileScopeProvider(); this.bodyResolver = new BodyResolver(); this.controlFlowAnalyzer = new ControlFlowAnalyzer(); this.declarationsChecker = new DeclarationsChecker(); @@ -240,11 +243,15 @@ public class InjectorForTopDownAnalyzerForJvm { this.resolveSession.setAnnotationResolve(annotationResolver); this.resolveSession.setDescriptorResolver(descriptorResolver); this.resolveSession.setJetImportFactory(jetImportsFactory); + this.resolveSession.setLazyDeclarationResolver(lazyDeclarationResolver); this.resolveSession.setQualifiedExpressionResolver(qualifiedExpressionResolver); this.resolveSession.setScopeProvider(scopeProvider); this.resolveSession.setScriptBodyResolver(scriptBodyResolver); this.resolveSession.setTypeResolver(typeResolver); + scopeProvider.setAdditionalFileScopesProvider(additionalFileScopeProvider); + scopeProvider.setDeclarationScopeProvider(declarationScopeProvider); + this.lazyTopDownAnalyzer.setBodyResolver(bodyResolver); this.lazyTopDownAnalyzer.setDeclarationResolver(declarationResolver); this.lazyTopDownAnalyzer.setKotlinCodeAnalyzer(resolveSession); @@ -334,8 +341,8 @@ public class InjectorForTopDownAnalyzerForJvm { jetImportsFactory.setProject(project); - scopeProvider.setAdditionalFileScopesProvider(additionalFileScopeProvider); - scopeProvider.setDeclarationScopeProvider(declarationScopeProvider); + lazyDeclarationResolver.setDeclarationScopeProvider(declarationScopeProvider); + lazyDeclarationResolver.setTopLevelDescriptorProvider(resolveSession); declarationScopeProvider.setFileScopeProvider(scopeProvider); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/di/InjectorForLazyResolve.java b/compiler/frontend/src/org/jetbrains/kotlin/di/InjectorForLazyResolve.java index 084d6a75b09..bb4a6a14867 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/di/InjectorForLazyResolve.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/di/InjectorForLazyResolve.java @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.AdditionalCheckerProvider; import org.jetbrains.kotlin.types.DynamicTypesSettings; import org.jetbrains.kotlin.resolve.lazy.ResolveSession; +import org.jetbrains.kotlin.resolve.lazy.ScopeProvider; import org.jetbrains.kotlin.context.LazyResolveToken; import org.jetbrains.kotlin.resolve.AnnotationResolver; import org.jetbrains.kotlin.resolve.calls.CallResolver; @@ -49,10 +50,10 @@ import org.jetbrains.kotlin.resolve.calls.CallCompleter; import org.jetbrains.kotlin.resolve.calls.CandidateResolver; import org.jetbrains.kotlin.resolve.calls.tasks.TaskPrioritizer; import org.jetbrains.kotlin.psi.JetImportsFactory; -import org.jetbrains.kotlin.resolve.lazy.ScopeProvider; -import org.jetbrains.kotlin.resolve.lazy.ScopeProvider.AdditionalFileScopeProvider; +import org.jetbrains.kotlin.resolve.lazy.LazyDeclarationResolver; import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProviderImpl; import org.jetbrains.kotlin.resolve.ScriptBodyResolver; +import org.jetbrains.kotlin.resolve.lazy.ScopeProvider.AdditionalFileScopeProvider; import org.jetbrains.annotations.NotNull; import javax.annotation.PreDestroy; @@ -71,6 +72,7 @@ public class InjectorForLazyResolve { private final AdditionalCheckerProvider additionalCheckerProvider; private final DynamicTypesSettings dynamicTypesSettings; private final ResolveSession resolveSession; + private final ScopeProvider scopeProvider; private final LazyResolveToken lazyResolveToken; private final AnnotationResolver annotationResolver; private final CallResolver callResolver; @@ -93,10 +95,10 @@ public class InjectorForLazyResolve { private final CandidateResolver candidateResolver; private final TaskPrioritizer taskPrioritizer; private final JetImportsFactory jetImportsFactory; - private final ScopeProvider scopeProvider; - private final AdditionalFileScopeProvider additionalFileScopeProvider; + private final LazyDeclarationResolver lazyDeclarationResolver; private final DeclarationScopeProviderImpl declarationScopeProvider; private final ScriptBodyResolver scriptBodyResolver; + private final AdditionalFileScopeProvider additionalFileScopeProvider; public InjectorForLazyResolve( @NotNull Project project, @@ -118,6 +120,7 @@ public class InjectorForLazyResolve { this.additionalCheckerProvider = additionalCheckerProvider; this.dynamicTypesSettings = dynamicTypesSettings; this.resolveSession = new ResolveSession(project, globalContext, moduleDescriptor, declarationProviderFactory, bindingTrace); + this.scopeProvider = new ScopeProvider(getResolveSession()); this.lazyResolveToken = new LazyResolveToken(); this.annotationResolver = new AnnotationResolver(); this.callResolver = new CallResolver(); @@ -140,19 +143,23 @@ public class InjectorForLazyResolve { this.callCompleter = new CallCompleter(argumentTypeResolver, candidateResolver); this.taskPrioritizer = new TaskPrioritizer(storageManager); this.jetImportsFactory = new JetImportsFactory(); - this.scopeProvider = new ScopeProvider(getResolveSession()); - this.additionalFileScopeProvider = new AdditionalFileScopeProvider(); - this.declarationScopeProvider = new DeclarationScopeProviderImpl(getResolveSession()); + this.lazyDeclarationResolver = new LazyDeclarationResolver(globalContext, bindingTrace); + this.declarationScopeProvider = new DeclarationScopeProviderImpl(lazyDeclarationResolver); this.scriptBodyResolver = new ScriptBodyResolver(); + this.additionalFileScopeProvider = new AdditionalFileScopeProvider(); this.resolveSession.setAnnotationResolve(annotationResolver); this.resolveSession.setDescriptorResolver(descriptorResolver); this.resolveSession.setJetImportFactory(jetImportsFactory); + this.resolveSession.setLazyDeclarationResolver(lazyDeclarationResolver); this.resolveSession.setQualifiedExpressionResolver(qualifiedExpressionResolver); this.resolveSession.setScopeProvider(scopeProvider); this.resolveSession.setScriptBodyResolver(scriptBodyResolver); this.resolveSession.setTypeResolver(typeResolver); + scopeProvider.setAdditionalFileScopesProvider(additionalFileScopeProvider); + scopeProvider.setDeclarationScopeProvider(declarationScopeProvider); + annotationResolver.setCallResolver(callResolver); annotationResolver.setStorageManager(storageManager); annotationResolver.setTypeResolver(typeResolver); @@ -212,8 +219,8 @@ public class InjectorForLazyResolve { jetImportsFactory.setProject(project); - scopeProvider.setAdditionalFileScopesProvider(additionalFileScopeProvider); - scopeProvider.setDeclarationScopeProvider(declarationScopeProvider); + lazyDeclarationResolver.setDeclarationScopeProvider(declarationScopeProvider); + lazyDeclarationResolver.setTopLevelDescriptorProvider(resolveSession); declarationScopeProvider.setFileScopeProvider(scopeProvider); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/di/InjectorForLazyTopDownAnalyzerBasic.java b/compiler/frontend/src/org/jetbrains/kotlin/di/InjectorForLazyTopDownAnalyzerBasic.java index 557b3e7ec5d..975e607b971 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/di/InjectorForLazyTopDownAnalyzerBasic.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/di/InjectorForLazyTopDownAnalyzerBasic.java @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap; import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory; import org.jetbrains.kotlin.resolve.lazy.ResolveSession; +import org.jetbrains.kotlin.resolve.lazy.ScopeProvider; import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer; import org.jetbrains.kotlin.resolve.AdditionalCheckerProvider.DefaultProvider; import org.jetbrains.kotlin.resolve.AnnotationResolver; @@ -50,10 +51,10 @@ import org.jetbrains.kotlin.resolve.calls.CallCompleter; import org.jetbrains.kotlin.resolve.calls.CandidateResolver; import org.jetbrains.kotlin.resolve.calls.tasks.TaskPrioritizer; import org.jetbrains.kotlin.psi.JetImportsFactory; -import org.jetbrains.kotlin.resolve.lazy.ScopeProvider; -import org.jetbrains.kotlin.resolve.lazy.ScopeProvider.AdditionalFileScopeProvider; +import org.jetbrains.kotlin.resolve.lazy.LazyDeclarationResolver; import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProviderImpl; import org.jetbrains.kotlin.resolve.ScriptBodyResolver; +import org.jetbrains.kotlin.resolve.lazy.ScopeProvider.AdditionalFileScopeProvider; import org.jetbrains.kotlin.resolve.BodyResolver; import org.jetbrains.kotlin.resolve.ControlFlowAnalyzer; import org.jetbrains.kotlin.resolve.DeclarationsChecker; @@ -80,6 +81,7 @@ public class InjectorForLazyTopDownAnalyzerBasic { private final PlatformToKotlinClassMap platformToKotlinClassMap; private final DeclarationProviderFactory declarationProviderFactory; private final ResolveSession resolveSession; + private final ScopeProvider scopeProvider; private final LazyTopDownAnalyzer lazyTopDownAnalyzer; private final DefaultProvider defaultProvider; private final AnnotationResolver annotationResolver; @@ -105,10 +107,10 @@ public class InjectorForLazyTopDownAnalyzerBasic { private final CandidateResolver candidateResolver; private final TaskPrioritizer taskPrioritizer; private final JetImportsFactory jetImportsFactory; - private final ScopeProvider scopeProvider; - private final AdditionalFileScopeProvider additionalFileScopeProvider; + private final LazyDeclarationResolver lazyDeclarationResolver; private final DeclarationScopeProviderImpl declarationScopeProvider; private final ScriptBodyResolver scriptBodyResolver; + private final AdditionalFileScopeProvider additionalFileScopeProvider; private final BodyResolver bodyResolver; private final ControlFlowAnalyzer controlFlowAnalyzer; private final DeclarationsChecker declarationsChecker; @@ -136,6 +138,7 @@ public class InjectorForLazyTopDownAnalyzerBasic { this.platformToKotlinClassMap = module.getPlatformToKotlinClassMap(); this.declarationProviderFactory = declarationProviderFactory; this.resolveSession = new ResolveSession(project, globalContext, module, declarationProviderFactory, bindingTrace); + this.scopeProvider = new ScopeProvider(getResolveSession()); this.lazyTopDownAnalyzer = new LazyTopDownAnalyzer(); this.defaultProvider = DefaultProvider.INSTANCE$; this.annotationResolver = new AnnotationResolver(); @@ -161,10 +164,10 @@ public class InjectorForLazyTopDownAnalyzerBasic { this.callCompleter = new CallCompleter(argumentTypeResolver, candidateResolver); this.taskPrioritizer = new TaskPrioritizer(storageManager); this.jetImportsFactory = new JetImportsFactory(); - this.scopeProvider = new ScopeProvider(getResolveSession()); - this.additionalFileScopeProvider = new AdditionalFileScopeProvider(); - this.declarationScopeProvider = new DeclarationScopeProviderImpl(getResolveSession()); + this.lazyDeclarationResolver = new LazyDeclarationResolver(globalContext, bindingTrace); + this.declarationScopeProvider = new DeclarationScopeProviderImpl(lazyDeclarationResolver); this.scriptBodyResolver = new ScriptBodyResolver(); + this.additionalFileScopeProvider = new AdditionalFileScopeProvider(); this.bodyResolver = new BodyResolver(); this.controlFlowAnalyzer = new ControlFlowAnalyzer(); this.declarationsChecker = new DeclarationsChecker(); @@ -179,11 +182,15 @@ public class InjectorForLazyTopDownAnalyzerBasic { this.resolveSession.setAnnotationResolve(annotationResolver); this.resolveSession.setDescriptorResolver(descriptorResolver); this.resolveSession.setJetImportFactory(jetImportsFactory); + this.resolveSession.setLazyDeclarationResolver(lazyDeclarationResolver); this.resolveSession.setQualifiedExpressionResolver(qualifiedExpressionResolver); this.resolveSession.setScopeProvider(scopeProvider); this.resolveSession.setScriptBodyResolver(scriptBodyResolver); this.resolveSession.setTypeResolver(typeResolver); + scopeProvider.setAdditionalFileScopesProvider(additionalFileScopeProvider); + scopeProvider.setDeclarationScopeProvider(declarationScopeProvider); + this.lazyTopDownAnalyzer.setBodyResolver(bodyResolver); this.lazyTopDownAnalyzer.setDeclarationResolver(declarationResolver); this.lazyTopDownAnalyzer.setKotlinCodeAnalyzer(resolveSession); @@ -252,8 +259,8 @@ public class InjectorForLazyTopDownAnalyzerBasic { jetImportsFactory.setProject(project); - scopeProvider.setAdditionalFileScopesProvider(additionalFileScopeProvider); - scopeProvider.setDeclarationScopeProvider(declarationScopeProvider); + lazyDeclarationResolver.setDeclarationScopeProvider(declarationScopeProvider); + lazyDeclarationResolver.setTopLevelDescriptorProvider(resolveSession); declarationScopeProvider.setFileScopeProvider(scopeProvider); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/DeclarationScopeProviderImpl.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/DeclarationScopeProviderImpl.java index a87c2c0a8c4..186c3d5578f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/DeclarationScopeProviderImpl.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/DeclarationScopeProviderImpl.java @@ -26,7 +26,7 @@ import javax.inject.Inject; public class DeclarationScopeProviderImpl implements DeclarationScopeProvider { - private final ResolveSession resolveSession; + private final LazyDeclarationResolver lazyDeclarationResolver; private FileScopeProvider fileScopeProvider; @@ -35,8 +35,8 @@ public class DeclarationScopeProviderImpl implements DeclarationScopeProvider { this.fileScopeProvider = fileScopeProvider; } - public DeclarationScopeProviderImpl(@NotNull ResolveSession resolveSession) { - this.resolveSession = resolveSession; + public DeclarationScopeProviderImpl(@NotNull LazyDeclarationResolver lazyDeclarationResolver) { + this.lazyDeclarationResolver = lazyDeclarationResolver; } @Override @@ -60,7 +60,7 @@ public class DeclarationScopeProviderImpl implements DeclarationScopeProvider { if (parentDeclaration instanceof JetClassOrObject) { JetClassOrObject classOrObject = (JetClassOrObject) parentDeclaration; - LazyClassDescriptor classDescriptor = (LazyClassDescriptor) resolveSession.getClassDescriptor(classOrObject); + LazyClassDescriptor classDescriptor = (LazyClassDescriptor) lazyDeclarationResolver.getClassDescriptor(classOrObject); if (jetDeclaration instanceof JetClassInitializer || jetDeclaration instanceof JetProperty) { return classDescriptor.getScopeForInitializerResolution(); } @@ -72,7 +72,7 @@ public class DeclarationScopeProviderImpl implements DeclarationScopeProvider { JetClassObject classObject = (JetClassObject) parentDeclaration; LazyClassDescriptor classObjectDescriptor = - (LazyClassDescriptor) resolveSession.getClassObjectDescriptor(classObject).getContainingDeclaration(); + (LazyClassDescriptor) lazyDeclarationResolver.getClassObjectDescriptor(classObject).getContainingDeclaration(); return classObjectDescriptor.getScopeForMemberDeclarationResolution(); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/KotlinCodeAnalyzer.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/KotlinCodeAnalyzer.java index 2fc8d7f2cb1..86f247b43d0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/KotlinCodeAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/KotlinCodeAnalyzer.java @@ -17,21 +17,19 @@ package org.jetbrains.kotlin.resolve.lazy; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.ReadOnly; -import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.descriptors.ClassDescriptor; +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; +import org.jetbrains.kotlin.descriptors.ModuleDescriptor; +import org.jetbrains.kotlin.descriptors.PackageFragmentProvider; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.psi.JetClassOrObject; import org.jetbrains.kotlin.psi.JetDeclaration; -import org.jetbrains.kotlin.psi.JetScript; import org.jetbrains.kotlin.resolve.BindingContext; -import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor; import java.util.Collection; -public interface KotlinCodeAnalyzer { - @Nullable - LazyPackageDescriptor getPackageFragment(@NotNull FqName fqName); +public interface KotlinCodeAnalyzer extends TopLevelDescriptorProvider { @NotNull ModuleDescriptor getModuleDescriptor(); @@ -43,9 +41,6 @@ public interface KotlinCodeAnalyzer { @NotNull ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject); - @NotNull - ScriptDescriptor getScriptDescriptor(@NotNull JetScript script); - @NotNull BindingContext getBindingContext(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyDeclarationResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyDeclarationResolver.java new file mode 100644 index 00000000000..4f4961f67ce --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyDeclarationResolver.java @@ -0,0 +1,251 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.resolve.lazy; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.context.GlobalContext; +import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.name.FqName; +import org.jetbrains.kotlin.name.Name; +import org.jetbrains.kotlin.psi.*; +import org.jetbrains.kotlin.renderer.DescriptorRenderer; +import org.jetbrains.kotlin.resolve.BindingContext; +import org.jetbrains.kotlin.resolve.BindingTrace; +import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor; +import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor; +import org.jetbrains.kotlin.resolve.scopes.JetScope; +import org.jetbrains.kotlin.storage.LockBasedLazyResolveStorageManager; + +import javax.inject.Inject; +import java.util.List; + +public class LazyDeclarationResolver { + + private final BindingTrace trace; + + private DeclarationScopeProvider scopeProvider; + private TopLevelDescriptorProvider topLevelDescriptorProvider; + + @Inject + public void setDeclarationScopeProvider(@NotNull DeclarationScopeProviderImpl scopeProvider) { + this.scopeProvider = scopeProvider; + } + + @Inject + public void setTopLevelDescriptorProvider(@NotNull TopLevelDescriptorProvider topLevelDescriptorProvider) { + this.topLevelDescriptorProvider = topLevelDescriptorProvider; + } + + @Deprecated + public LazyDeclarationResolver( + @NotNull GlobalContext globalContext, + @NotNull BindingTrace delegationTrace + ) { + LockBasedLazyResolveStorageManager lockBasedLazyResolveStorageManager = + new LockBasedLazyResolveStorageManager(globalContext.getStorageManager()); + + this.trace = lockBasedLazyResolveStorageManager.createSafeTrace(delegationTrace); + } + + @NotNull + public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject) { + if (classOrObject instanceof JetObjectDeclaration) { + JetObjectDeclaration objectDeclaration = (JetObjectDeclaration) classOrObject; + JetClassObject classObjectElement = objectDeclaration.getClassObjectElement(); + if (classObjectElement != null) { + return getClassObjectDescriptor(classObjectElement); + } + } + JetScope resolutionScope = resolutionScopeToResolveDeclaration(classOrObject); + + // Why not use the result here. Because it may be that there is a redeclaration: + // class A {} class A { fun foo(): A} + // and if we find the class by name only, we may b-not get the right one. + // This call is only needed to make sure the classes are written to trace + ClassifierDescriptor scopeDescriptor = resolutionScope.getClassifier(classOrObject.getNameAsSafeName()); + DeclarationDescriptor descriptor = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject); + + if (descriptor == null) { + throw new IllegalArgumentException( + String.format("Could not find a classifier for %s.\n" + + "Found descriptor: %s (%s).\n", + JetPsiUtil.getElementTextWithContext(classOrObject), + scopeDescriptor != null ? DescriptorRenderer.DEBUG_TEXT.render(scopeDescriptor) : "null", + scopeDescriptor != null ? (scopeDescriptor.getContainingDeclaration().getClass()) : null)); + } + + return (ClassDescriptor) descriptor; + } + + @NotNull + /*package*/ LazyClassDescriptor getClassObjectDescriptor(@NotNull JetClassObject classObject) { + JetClass aClass = JetStubbedPsiUtil.getContainingDeclaration(classObject, JetClass.class); + + LazyClassDescriptor parentClassDescriptor; + + if (aClass != null) { + parentClassDescriptor = (LazyClassDescriptor) getClassDescriptor(aClass); + } + else { + // Class object in object is an error but we want to find descriptors even for this case + JetObjectDeclaration objectDeclaration = PsiTreeUtil.getParentOfType(classObject, JetObjectDeclaration.class); + assert objectDeclaration != null : String.format("Class object %s can be in class or object in file %s", classObject, classObject.getContainingFile().getText()); + parentClassDescriptor = (LazyClassDescriptor) getClassDescriptor(objectDeclaration); + } + + // Activate resolution and writing to trace + parentClassDescriptor.getClassObjectDescriptor(); + parentClassDescriptor.getDescriptorsForExtraClassObjects(); + DeclarationDescriptor classObjectDescriptor = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classObject.getObjectDeclaration()); + assert classObjectDescriptor != null : "No descriptor found for " + JetPsiUtil.getElementTextWithContext(classObject); + + return (LazyClassDescriptor) classObjectDescriptor; + } + + @NotNull + private BindingContext getBindingContext() { + return trace.getBindingContext(); + } + + @NotNull + public DeclarationDescriptor resolveToDescriptor(@NotNull JetDeclaration declaration) { + DeclarationDescriptor result = declaration.accept(new JetVisitor() { + @Override + public DeclarationDescriptor visitClass(@NotNull JetClass klass, Void data) { + return getClassDescriptor(klass); + } + + @Override + public DeclarationDescriptor visitObjectDeclaration(@NotNull JetObjectDeclaration declaration, Void data) { + PsiElement parent = declaration.getParent(); + if (parent instanceof JetClassObject) { + JetClassObject jetClassObject = (JetClassObject) parent; + return resolveToDescriptor(jetClassObject); + } + return getClassDescriptor(declaration); + } + + @Override + public DeclarationDescriptor visitClassObject(@NotNull JetClassObject classObject, Void data) { + return getClassObjectDescriptor(classObject); + } + + @Override + public DeclarationDescriptor visitTypeParameter(@NotNull JetTypeParameter parameter, Void data) { + JetTypeParameterListOwner ownerElement = PsiTreeUtil.getParentOfType(parameter, JetTypeParameterListOwner.class); + DeclarationDescriptor ownerDescriptor = resolveToDescriptor(ownerElement); + + List typeParameters; + if (ownerDescriptor instanceof CallableDescriptor) { + CallableDescriptor callableDescriptor = (CallableDescriptor) ownerDescriptor; + typeParameters = callableDescriptor.getTypeParameters(); + } + else if (ownerDescriptor instanceof ClassDescriptor) { + ClassDescriptor classDescriptor = (ClassDescriptor) ownerDescriptor; + typeParameters = classDescriptor.getTypeConstructor().getParameters(); + } + else { + throw new IllegalStateException("Unknown owner kind for a type parameter: " + ownerDescriptor); + } + + Name name = parameter.getNameAsSafeName(); + for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) { + if (typeParameterDescriptor.getName().equals(name)) { + return typeParameterDescriptor; + } + } + + throw new IllegalStateException("Type parameter " + name + " not found for " + ownerDescriptor); + } + + @Override + public DeclarationDescriptor visitNamedFunction(@NotNull JetNamedFunction function, Void data) { + JetScope scopeForDeclaration = resolutionScopeToResolveDeclaration(function); + scopeForDeclaration.getFunctions(function.getNameAsSafeName()); + return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, function); + } + + @Override + public DeclarationDescriptor visitParameter(@NotNull JetParameter parameter, Void data) { + PsiElement grandFather = parameter.getParent().getParent(); + if (grandFather instanceof JetClass) { + JetClass jetClass = (JetClass) grandFather; + // This is a primary constructor parameter + ClassDescriptor classDescriptor = getClassDescriptor(jetClass); + if (parameter.hasValOrVarNode()) { + classDescriptor.getDefaultType().getMemberScope().getProperties(parameter.getNameAsSafeName()); + return getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); + } + else { + ConstructorDescriptor constructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); + assert constructor != null: "There are constructor parameters found, so a constructor should also exist"; + constructor.getValueParameters(); + return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter); + } + } + else if (grandFather instanceof JetNamedFunction) { + FunctionDescriptor function = (FunctionDescriptor) visitNamedFunction((JetNamedFunction) grandFather, data); + function.getValueParameters(); + return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter); + } + else { + //TODO: support parameters in accessors and other places(?) + return super.visitParameter(parameter, data); + } + } + + @Override + public DeclarationDescriptor visitProperty(@NotNull JetProperty property, Void data) { + JetScope scopeForDeclaration = resolutionScopeToResolveDeclaration(property); + scopeForDeclaration.getProperties(property.getNameAsSafeName()); + return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, property); + } + + @Override + public DeclarationDescriptor visitScript(@NotNull JetScript script, Void data) { + return topLevelDescriptorProvider.getScriptDescriptor(script); + } + + @Override + public DeclarationDescriptor visitJetElement(@NotNull JetElement element, Void data) { + throw new IllegalArgumentException("Unsupported declaration type: " + element + " " + + JetPsiUtil.getElementTextWithContext(element)); + } + }, null); + if (result == null) { + throw new IllegalStateException("No descriptor resolved for " + declaration + ":\n" + + JetPsiUtil.getElementTextWithContext(declaration)); + } + return result; + } + + @NotNull + /*package*/ JetScope resolutionScopeToResolveDeclaration(@NotNull JetDeclaration declaration) { + boolean isTopLevel = JetStubbedPsiUtil.getContainingDeclaration(declaration) == null; + if (isTopLevel) { // for top level declarations we search directly in package because of possible conflicts with imports + FqName fqName = ((JetFile) declaration.getContainingFile()).getPackageFqName(); + LazyPackageDescriptor packageDescriptor = topLevelDescriptorProvider.getPackageFragment(fqName); + assert packageDescriptor != null; + return packageDescriptor.getMemberScope(); + } + else { + return scopeProvider.getResolutionScopeForDeclaration(declaration); + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java index 50e81983c66..d51bc99845d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java @@ -18,8 +18,6 @@ package org.jetbrains.kotlin.resolve.lazy; import com.google.common.collect.Lists; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import kotlin.Function1; @@ -33,13 +31,15 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.renderer.DescriptorRenderer; import org.jetbrains.kotlin.resolve.*; import org.jetbrains.kotlin.resolve.lazy.data.JetClassLikeInfo; import org.jetbrains.kotlin.resolve.lazy.data.JetScriptInfo; import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory; import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider; -import org.jetbrains.kotlin.resolve.lazy.descriptors.*; +import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotations; +import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationsContextImpl; +import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor; +import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor; import org.jetbrains.kotlin.resolve.scopes.JetScope; import org.jetbrains.kotlin.storage.*; @@ -73,6 +73,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { private TypeResolver typeResolver; private QualifiedExpressionResolver qualifiedExpressionResolver; private ScriptBodyResolver scriptBodyResolver; + private LazyDeclarationResolver lazyDeclarationResolver; @Inject public void setJetImportFactory(JetImportsFactory jetImportFactory) { @@ -109,6 +110,11 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { this.scriptBodyResolver = scriptBodyResolver; } + @Inject + public void setLazyDeclarationResolver(LazyDeclarationResolver lazyDeclarationResolver) { + this.lazyDeclarationResolver = lazyDeclarationResolver; + } + // Only calls from injectors expected @Deprecated public ResolveSession( @@ -126,13 +132,14 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { this.trace = lockBasedLazyResolveStorageManager.createSafeTrace(delegationTrace); this.module = rootDescriptor; - this.packages = storageManager.createMemoizedFunctionWithNullableValues(new MemoizedFunctionToNullable() { - @Nullable - @Override - public LazyPackageDescriptor invoke(FqName fqName) { - return createPackage(fqName); - } - }); + this.packages = + storageManager.createMemoizedFunctionWithNullableValues(new MemoizedFunctionToNullable() { + @Nullable + @Override + public LazyPackageDescriptor invoke(FqName fqName) { + return createPackage(fqName); + } + }); this.declarationProviderFactory = declarationProviderFactory; @@ -146,7 +153,8 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { @NotNull @Override public Collection getSubPackagesOf( - @NotNull FqName fqName, @NotNull Function1 nameFilter) { + @NotNull FqName fqName, @NotNull Function1 nameFilter + ) { LazyPackageDescriptor packageDescriptor = getPackageFragment(fqName); if (packageDescriptor == null) { return Collections.emptyList(); @@ -259,37 +267,12 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { @Override @NotNull public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject) { - if (classOrObject instanceof JetObjectDeclaration) { - JetObjectDeclaration objectDeclaration = (JetObjectDeclaration) classOrObject; - JetClassObject classObjectElement = objectDeclaration.getClassObjectElement(); - if (classObjectElement != null) { - return getClassObjectDescriptor(classObjectElement); - } - } - JetScope resolutionScope = resolutionScopeToResolveDeclaration(classOrObject); - - // Why not use the result here. Because it may be that there is a redeclaration: - // class A {} class A { fun foo(): A} - // and if we find the class by name only, we may b-not get the right one. - // This call is only needed to make sure the classes are written to trace - ClassifierDescriptor scopeDescriptor = resolutionScope.getClassifier(classOrObject.getNameAsSafeName()); - DeclarationDescriptor descriptor = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject); - - if (descriptor == null) { - throw new IllegalArgumentException( - String.format("Could not find a classifier for %s.\n" + - "Found descriptor: %s (%s).\n", - JetPsiUtil.getElementTextWithContext(classOrObject), - scopeDescriptor != null ? DescriptorRenderer.DEBUG_TEXT.render(scopeDescriptor) : "null", - scopeDescriptor != null ? (scopeDescriptor.getContainingDeclaration().getClass()) : null)); - } - - return (ClassDescriptor) descriptor; + return lazyDeclarationResolver.getClassDescriptor(classOrObject); } @NotNull public ClassDescriptor getClassDescriptorForScript(@NotNull JetScript script) { - JetScope resolutionScope = resolutionScopeToResolveDeclaration(script); + JetScope resolutionScope = lazyDeclarationResolver.resolutionScopeToResolveDeclaration(script); FqName fqName = ScriptNameUtil.classNameForScript(script); ClassifierDescriptor classifier = resolutionScope.getClassifier(fqName.shortName()); assert classifier != null : "No descriptor for " + fqName + " in file " + script.getContainingFile(); @@ -302,31 +285,6 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { return scriptDescriptors.invoke(script); } - @NotNull - /*package*/ LazyClassDescriptor getClassObjectDescriptor(@NotNull JetClassObject classObject) { - JetClass aClass = JetStubbedPsiUtil.getContainingDeclaration(classObject, JetClass.class); - - LazyClassDescriptor parentClassDescriptor; - - if (aClass != null) { - parentClassDescriptor = (LazyClassDescriptor) getClassDescriptor(aClass); - } - else { - // Class object in object is an error but we want to find descriptors even for this case - JetObjectDeclaration objectDeclaration = PsiTreeUtil.getParentOfType(classObject, JetObjectDeclaration.class); - assert objectDeclaration != null : String.format("Class object %s can be in class or object in file %s", classObject, classObject.getContainingFile().getText()); - parentClassDescriptor = (LazyClassDescriptor) getClassDescriptor(objectDeclaration); - } - - // Activate resolution and writing to trace - parentClassDescriptor.getClassObjectDescriptor(); - parentClassDescriptor.getDescriptorsForExtraClassObjects(); - DeclarationDescriptor classObjectDescriptor = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classObject.getObjectDeclaration()); - assert classObjectDescriptor != null : "No descriptor found for " + JetPsiUtil.getElementTextWithContext(classObject); - - return (LazyClassDescriptor) classObjectDescriptor; - } - @Override @NotNull public BindingContext getBindingContext() { @@ -348,114 +306,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { @Override @NotNull public DeclarationDescriptor resolveToDescriptor(@NotNull JetDeclaration declaration) { - DeclarationDescriptor result = declaration.accept(new JetVisitor() { - @Override - public DeclarationDescriptor visitClass(@NotNull JetClass klass, Void data) { - return getClassDescriptor(klass); - } - - @Override - public DeclarationDescriptor visitObjectDeclaration(@NotNull JetObjectDeclaration declaration, Void data) { - PsiElement parent = declaration.getParent(); - if (parent instanceof JetClassObject) { - JetClassObject jetClassObject = (JetClassObject) parent; - return resolveToDescriptor(jetClassObject); - } - return getClassDescriptor(declaration); - } - - @Override - public DeclarationDescriptor visitClassObject(@NotNull JetClassObject classObject, Void data) { - return getClassObjectDescriptor(classObject); - } - - @Override - public DeclarationDescriptor visitTypeParameter(@NotNull JetTypeParameter parameter, Void data) { - JetTypeParameterListOwner ownerElement = PsiTreeUtil.getParentOfType(parameter, JetTypeParameterListOwner.class); - DeclarationDescriptor ownerDescriptor = resolveToDescriptor(ownerElement); - - List typeParameters; - if (ownerDescriptor instanceof CallableDescriptor) { - CallableDescriptor callableDescriptor = (CallableDescriptor) ownerDescriptor; - typeParameters = callableDescriptor.getTypeParameters(); - } - else if (ownerDescriptor instanceof ClassDescriptor) { - ClassDescriptor classDescriptor = (ClassDescriptor) ownerDescriptor; - typeParameters = classDescriptor.getTypeConstructor().getParameters(); - } - else { - throw new IllegalStateException("Unknown owner kind for a type parameter: " + ownerDescriptor); - } - - Name name = parameter.getNameAsSafeName(); - for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) { - if (typeParameterDescriptor.getName().equals(name)) { - return typeParameterDescriptor; - } - } - - throw new IllegalStateException("Type parameter " + name + " not found for " + ownerDescriptor); - } - - @Override - public DeclarationDescriptor visitNamedFunction(@NotNull JetNamedFunction function, Void data) { - JetScope scopeForDeclaration = resolutionScopeToResolveDeclaration(function); - scopeForDeclaration.getFunctions(function.getNameAsSafeName()); - return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, function); - } - - @Override - public DeclarationDescriptor visitParameter(@NotNull JetParameter parameter, Void data) { - PsiElement grandFather = parameter.getParent().getParent(); - if (grandFather instanceof JetClass) { - JetClass jetClass = (JetClass) grandFather; - // This is a primary constructor parameter - ClassDescriptor classDescriptor = getClassDescriptor(jetClass); - if (parameter.hasValOrVarNode()) { - classDescriptor.getDefaultType().getMemberScope().getProperties(parameter.getNameAsSafeName()); - return getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); - } - else { - ConstructorDescriptor constructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); - assert constructor != null: "There are constructor parameters found, so a constructor should also exist"; - constructor.getValueParameters(); - return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter); - } - } - else if (grandFather instanceof JetNamedFunction) { - FunctionDescriptor function = (FunctionDescriptor) visitNamedFunction((JetNamedFunction) grandFather, data); - function.getValueParameters(); - return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter); - } - else { - //TODO: support parameters in accessors and other places(?) - return super.visitParameter(parameter, data); - } - } - - @Override - public DeclarationDescriptor visitProperty(@NotNull JetProperty property, Void data) { - JetScope scopeForDeclaration = resolutionScopeToResolveDeclaration(property); - scopeForDeclaration.getProperties(property.getNameAsSafeName()); - return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, property); - } - - @Override - public DeclarationDescriptor visitScript(@NotNull JetScript script, Void data) { - return scriptDescriptors.invoke(script); - } - - @Override - public DeclarationDescriptor visitJetElement(@NotNull JetElement element, Void data) { - throw new IllegalArgumentException("Unsupported declaration type: " + element + " " + - JetPsiUtil.getElementTextWithContext(element)); - } - }, null); - if (result == null) { - throw new IllegalStateException("No descriptor resolved for " + declaration + ":\n" + - JetPsiUtil.getElementTextWithContext(declaration)); - } - return result; + return lazyDeclarationResolver.resolveToDescriptor(declaration); } @NotNull @@ -530,18 +381,4 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext { public QualifiedExpressionResolver getQualifiedExpressionResolver() { return qualifiedExpressionResolver; } - - @NotNull - private JetScope resolutionScopeToResolveDeclaration(@NotNull JetDeclaration declaration) { - boolean isTopLevel = JetStubbedPsiUtil.getContainingDeclaration(declaration) == null; - if (isTopLevel) { // for top level declarations we search directly in package because of possible conflicts with imports - FqName fqName = ((JetFile) declaration.getContainingFile()).getPackageFqName(); - LazyPackageDescriptor packageDescriptor = getPackageFragment(fqName); - assert packageDescriptor != null; - return packageDescriptor.getMemberScope(); - } - else { - return getScopeProvider().getResolutionScopeForDeclaration(declaration); - } - } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/TopLevelDescriptorProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/TopLevelDescriptorProvider.kt new file mode 100644 index 00000000000..c837121c095 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/TopLevelDescriptorProvider.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.resolve.lazy + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ScriptDescriptor +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.JetScript +import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor + +public trait TopLevelDescriptorProvider { + fun getPackageFragment(fqName: FqName): LazyPackageDescriptor? + + fun getScriptDescriptor(script: JetScript): ScriptDescriptor + + fun getTopLevelClassDescriptors(fqName: FqName): Collection +} diff --git a/generators/src/org/jetbrains/kotlin/generators/injectors/GenerateInjectors.kt b/generators/src/org/jetbrains/kotlin/generators/injectors/GenerateInjectors.kt index c1ddf9d28e4..182439e04e5 100644 --- a/generators/src/org/jetbrains/kotlin/generators/injectors/GenerateInjectors.kt +++ b/generators/src/org/jetbrains/kotlin/generators/injectors/GenerateInjectors.kt @@ -259,6 +259,7 @@ private fun generatorForLazyResolve() = parameter() publicField() + field() field() } @@ -271,6 +272,7 @@ private fun DependencyInjectorGenerator.commonForResolveSessionBased() { parameter() publicField() + field() } private fun DependencyInjectorGenerator.commonForJavaTopDownAnalyzer() { diff --git a/js/js.frontend/src/org/jetbrains/kotlin/di/InjectorForTopDownAnalyzerForJs.java b/js/js.frontend/src/org/jetbrains/kotlin/di/InjectorForTopDownAnalyzerForJs.java index 7cbf4cd8b8e..4a17c586033 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/di/InjectorForTopDownAnalyzerForJs.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/di/InjectorForTopDownAnalyzerForJs.java @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap; import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory; import org.jetbrains.kotlin.resolve.lazy.ResolveSession; +import org.jetbrains.kotlin.resolve.lazy.ScopeProvider; import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer; import org.jetbrains.kotlin.js.resolve.KotlinJsCheckerProvider; import org.jetbrains.kotlin.types.DynamicTypesAllowed; @@ -50,10 +51,10 @@ import org.jetbrains.kotlin.resolve.calls.CallCompleter; import org.jetbrains.kotlin.resolve.calls.CandidateResolver; import org.jetbrains.kotlin.resolve.calls.tasks.TaskPrioritizer; import org.jetbrains.kotlin.psi.JetImportsFactory; -import org.jetbrains.kotlin.resolve.lazy.ScopeProvider; -import org.jetbrains.kotlin.resolve.lazy.ScopeProvider.AdditionalFileScopeProvider; +import org.jetbrains.kotlin.resolve.lazy.LazyDeclarationResolver; import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProviderImpl; import org.jetbrains.kotlin.resolve.ScriptBodyResolver; +import org.jetbrains.kotlin.resolve.lazy.ScopeProvider.AdditionalFileScopeProvider; import org.jetbrains.kotlin.resolve.BodyResolver; import org.jetbrains.kotlin.resolve.ControlFlowAnalyzer; import org.jetbrains.kotlin.resolve.DeclarationsChecker; @@ -80,6 +81,7 @@ public class InjectorForTopDownAnalyzerForJs { private final PlatformToKotlinClassMap platformToKotlinClassMap; private final DeclarationProviderFactory declarationProviderFactory; private final ResolveSession resolveSession; + private final ScopeProvider scopeProvider; private final LazyTopDownAnalyzer lazyTopDownAnalyzer; private final KotlinJsCheckerProvider kotlinJsCheckerProvider; private final DynamicTypesAllowed dynamicTypesAllowed; @@ -105,10 +107,10 @@ public class InjectorForTopDownAnalyzerForJs { private final CandidateResolver candidateResolver; private final TaskPrioritizer taskPrioritizer; private final JetImportsFactory jetImportsFactory; - private final ScopeProvider scopeProvider; - private final AdditionalFileScopeProvider additionalFileScopeProvider; + private final LazyDeclarationResolver lazyDeclarationResolver; private final DeclarationScopeProviderImpl declarationScopeProvider; private final ScriptBodyResolver scriptBodyResolver; + private final AdditionalFileScopeProvider additionalFileScopeProvider; private final BodyResolver bodyResolver; private final ControlFlowAnalyzer controlFlowAnalyzer; private final DeclarationsChecker declarationsChecker; @@ -136,6 +138,7 @@ public class InjectorForTopDownAnalyzerForJs { this.platformToKotlinClassMap = module.getPlatformToKotlinClassMap(); this.declarationProviderFactory = declarationProviderFactory; this.resolveSession = new ResolveSession(project, globalContext, module, declarationProviderFactory, bindingTrace); + this.scopeProvider = new ScopeProvider(getResolveSession()); this.lazyTopDownAnalyzer = new LazyTopDownAnalyzer(); this.kotlinJsCheckerProvider = KotlinJsCheckerProvider.INSTANCE$; this.dynamicTypesAllowed = new DynamicTypesAllowed(); @@ -161,10 +164,10 @@ public class InjectorForTopDownAnalyzerForJs { this.callCompleter = new CallCompleter(argumentTypeResolver, candidateResolver); this.taskPrioritizer = new TaskPrioritizer(storageManager); this.jetImportsFactory = new JetImportsFactory(); - this.scopeProvider = new ScopeProvider(getResolveSession()); - this.additionalFileScopeProvider = new AdditionalFileScopeProvider(); - this.declarationScopeProvider = new DeclarationScopeProviderImpl(getResolveSession()); + this.lazyDeclarationResolver = new LazyDeclarationResolver(globalContext, bindingTrace); + this.declarationScopeProvider = new DeclarationScopeProviderImpl(lazyDeclarationResolver); this.scriptBodyResolver = new ScriptBodyResolver(); + this.additionalFileScopeProvider = new AdditionalFileScopeProvider(); this.bodyResolver = new BodyResolver(); this.controlFlowAnalyzer = new ControlFlowAnalyzer(); this.declarationsChecker = new DeclarationsChecker(); @@ -179,11 +182,15 @@ public class InjectorForTopDownAnalyzerForJs { this.resolveSession.setAnnotationResolve(annotationResolver); this.resolveSession.setDescriptorResolver(descriptorResolver); this.resolveSession.setJetImportFactory(jetImportsFactory); + this.resolveSession.setLazyDeclarationResolver(lazyDeclarationResolver); this.resolveSession.setQualifiedExpressionResolver(qualifiedExpressionResolver); this.resolveSession.setScopeProvider(scopeProvider); this.resolveSession.setScriptBodyResolver(scriptBodyResolver); this.resolveSession.setTypeResolver(typeResolver); + scopeProvider.setAdditionalFileScopesProvider(additionalFileScopeProvider); + scopeProvider.setDeclarationScopeProvider(declarationScopeProvider); + this.lazyTopDownAnalyzer.setBodyResolver(bodyResolver); this.lazyTopDownAnalyzer.setDeclarationResolver(declarationResolver); this.lazyTopDownAnalyzer.setKotlinCodeAnalyzer(resolveSession); @@ -252,8 +259,8 @@ public class InjectorForTopDownAnalyzerForJs { jetImportsFactory.setProject(project); - scopeProvider.setAdditionalFileScopesProvider(additionalFileScopeProvider); - scopeProvider.setDeclarationScopeProvider(declarationScopeProvider); + lazyDeclarationResolver.setDeclarationScopeProvider(declarationScopeProvider); + lazyDeclarationResolver.setTopLevelDescriptorProvider(resolveSession); declarationScopeProvider.setFileScopeProvider(scopeProvider);