diff --git a/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/ElementResolver.kt b/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/ElementResolver.kt deleted file mode 100644 index 1395ba27c9d..00000000000 --- a/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/ElementResolver.kt +++ /dev/null @@ -1,427 +0,0 @@ -/* - * 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.analyzer.computeTypeInContext -import org.jetbrains.kotlin.cfg.JetFlowInformationProvider -import org.jetbrains.kotlin.container.get -import org.jetbrains.kotlin.context.SimpleGlobalContext -import org.jetbrains.kotlin.context.withModule -import org.jetbrains.kotlin.context.withProject -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.frontend.di.createContainerForBodyResolve -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext -import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.resolve.* -import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo -import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor -import org.jetbrains.kotlin.resolve.scopes.JetScope -import org.jetbrains.kotlin.resolve.util.getScopeAndDataFlowForAnalyzeFragment -import org.jetbrains.kotlin.types.TypeUtils - -public abstract class ElementResolver protected constructor( - public val resolveSession: ResolveSession -) { - protected open fun getElementAdditionalResolve(resolveElement: JetElement, contextElement: JetElement, bodyResolveMode: BodyResolveMode): BindingContext { - return performElementAdditionalResolve(resolveElement, resolveElement, bodyResolveMode).first - } - - protected open fun probablyNothingCallableNames(): ProbablyNothingCallableNames - = throw UnsupportedOperationException("Cannot use partial body resolve with no Nothing-functions index"); - - public fun resolveToElement(element: JetElement, bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext { - var contextElement = element - - val elementOfAdditionalResolve = findElementOfAdditionalResolve(contextElement) - - if (elementOfAdditionalResolve is JetParameter) { - // Parameters for function literal could be met inside other parameters. We can't make resolveToDescriptors for internal elements. - contextElement = elementOfAdditionalResolve - } - else if (elementOfAdditionalResolve != null) { - return getElementAdditionalResolve(elementOfAdditionalResolve, contextElement, bodyResolveMode) - } - - val declaration = contextElement.getParentOfType(false) - if (declaration != null && declaration !is JetClassInitializer) { - // Activate descriptor resolution - resolveSession.resolveToDescriptor(declaration) - } - - return resolveSession.getBindingContext() - } - - private fun findElementOfAdditionalResolve(element: JetElement): JetElement? { - val elementOfAdditionalResolve = JetPsiUtil.getTopmostParentOfTypes( - element, - javaClass(), - javaClass(), - javaClass(), - javaClass(), - javaClass(), - javaClass(), - javaClass(), - javaClass(), - javaClass(), - javaClass(), - javaClass(), - javaClass(), - javaClass()) as JetElement? - - when (elementOfAdditionalResolve) { - null -> { - // Case of JetAnnotationEntry on top level class - if (element is JetAnnotationEntry) { - return element - } - - return null - } - - is JetPackageDirective -> return element - - is JetParameter -> { - val klass = elementOfAdditionalResolve.getParentOfType(strict = true) - if (klass != null && elementOfAdditionalResolve.getParent() == klass.getPrimaryConstructorParameterList()) { - return klass - } - - return elementOfAdditionalResolve - } - - else -> return elementOfAdditionalResolve - } - } - - protected fun performElementAdditionalResolve(resolveElement: JetElement, contextElement: JetElement, bodyResolveMode: BodyResolveMode): Pair { - val file = resolveElement.getContainingJetFile() - - var statementFilterUsed = StatementFilter.NONE - - fun createStatementFilter(): StatementFilter { - assert(resolveElement is JetDeclaration) - if (bodyResolveMode != BodyResolveMode.FULL) { - statementFilterUsed = PartialBodyResolveFilter( - contextElement, - resolveElement as JetDeclaration, - probablyNothingCallableNames(), - bodyResolveMode == BodyResolveMode.PARTIAL_FOR_COMPLETION) - } - return statementFilterUsed - } - - val trace: BindingTrace = when (resolveElement) { - is JetNamedFunction -> functionAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter()) - - is JetClassInitializer -> initializerAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter()) - - is JetSecondaryConstructor -> secondaryConstructorAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter()) - - is JetProperty -> propertyAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter()) - - is JetDelegationSpecifierList -> delegationSpecifierAdditionalResolve(resolveSession, resolveElement, resolveElement.getParent() as JetClassOrObject, file) - - is JetInitializerList -> delegationSpecifierAdditionalResolve(resolveSession, resolveElement, resolveElement.getParent() as JetEnumEntry, file) - - is JetImportList -> { - val scope = resolveSession.getFileScopeProvider().getFileScope(resolveElement.getContainingJetFile()) - scope.forceResolveAllImports() - resolveSession.getTrace() - } - - is JetAnnotationEntry -> annotationAdditionalResolve(resolveSession, resolveElement) - - is JetClass -> constructorAdditionalResolve(resolveSession, resolveElement, file) - - is JetTypeParameter -> typeParameterAdditionalResolve(resolveSession, resolveElement) - - is JetTypeConstraint -> typeConstraintAdditionalResolve(resolveSession, resolveElement) - - is JetCodeFragment -> codeFragmentAdditionalResolve(resolveSession, resolveElement, bodyResolveMode) - - else -> { - if (resolveElement.getParentOfType(true) != null) { - packageRefAdditionalResolve(resolveSession, resolveElement) - } - else { - error("Invalid type of the topmost parent: $resolveElement\n${resolveElement.getElementTextWithContext()}") - } - } - } - - val controlFlowTrace = DelegatingBindingTrace(trace.getBindingContext(), "Element control flow resolve", resolveElement) - JetFlowInformationProvider(resolveElement, controlFlowTrace).checkDeclaration() - controlFlowTrace.addOwnDataTo(trace, null, false) - - return Pair(trace.getBindingContext(), statementFilterUsed) - } - - private fun packageRefAdditionalResolve(resolveSession: ResolveSession, jetElement: JetElement): BindingTrace { - val trace = createDelegatingTrace(jetElement) - - if (jetElement is JetSimpleNameExpression) { - val header = jetElement.getParentOfType(true)!! - - if (trace.getBindingContext()[BindingContext.RESOLUTION_SCOPE, jetElement] == null) { - val scope = resolveSession.getModuleDescriptor().getPackage(header.getFqName(jetElement).parent()).memberScope - trace.record(BindingContext.RESOLUTION_SCOPE, jetElement, scope) - } - - if (Name.isValidIdentifier(jetElement.getReferencedName())) { - if (trace.getBindingContext()[BindingContext.REFERENCE_TARGET, jetElement] == null) { - val fqName = header.getFqName(jetElement) - val packageDescriptor = resolveSession.getModuleDescriptor().getPackage(fqName) - trace.record(BindingContext.REFERENCE_TARGET, jetElement, packageDescriptor) - } - } - } - - return trace - } - - private fun typeConstraintAdditionalResolve(analyzer: KotlinCodeAnalyzer, jetTypeConstraint: JetTypeConstraint): BindingTrace { - val declaration = jetTypeConstraint.getParentOfType(true)!! - val descriptor = analyzer.resolveToDescriptor(declaration) as ClassDescriptor - - for (parameterDescriptor in descriptor.getTypeConstructor().getParameters()) { - ForceResolveUtil.forceResolveAllContents(parameterDescriptor) - } - - return resolveSession.getTrace() - } - - private fun codeFragmentAdditionalResolve(resolveSession: ResolveSession, codeFragment: JetCodeFragment, bodyResolveMode: BodyResolveMode): BindingTrace { - val trace = createDelegatingTrace(codeFragment) - - val codeFragmentExpression = codeFragment.getContentElement() as? JetExpression ?: return trace - - val (scopeForContextElement, dataFlowInfoForContextElement) = codeFragment.getScopeAndDataFlowForAnalyzeFragment(resolveSession) { - val contextResolveMode = if (bodyResolveMode == BodyResolveMode.PARTIAL) - BodyResolveMode.PARTIAL_FOR_COMPLETION - else - bodyResolveMode - - resolveToElement(it, contextResolveMode) - } ?: return trace - - codeFragmentExpression.computeTypeInContext(scopeForContextElement, trace, dataFlowInfoForContextElement, - TypeUtils.NO_EXPECTED_TYPE, resolveSession.getModuleDescriptor()) - - return trace - } - - private fun annotationAdditionalResolve(resolveSession: ResolveSession, jetAnnotationEntry: JetAnnotationEntry): BindingTrace { - val modifierList = jetAnnotationEntry.getParentOfType(true) - val declaration = modifierList?.getParentOfType(true) - if (declaration != null) { - doResolveAnnotations(getAnnotationsByDeclaration(resolveSession, modifierList!!, declaration)) - } - else { - val fileAnnotationList = jetAnnotationEntry.getParentOfType(true) - if (fileAnnotationList != null) { - doResolveAnnotations(resolveSession.getFileAnnotations(fileAnnotationList.getContainingJetFile())) - } - if (modifierList != null && modifierList.getParent() is JetFile) { - doResolveAnnotations(resolveSession.getDanglingAnnotations(modifierList.getContainingJetFile())) - } - } - - return resolveSession.getTrace() - } - - private fun doResolveAnnotations(annotations: Annotations) { - ForceResolveUtil.forceResolveAllContents(annotations) - } - - private fun getAnnotationsByDeclaration(resolveSession: ResolveSession, modifierList: JetModifierList, declaration: JetDeclaration): Annotations { - var descriptor = resolveSession.resolveToDescriptor(declaration) - if (declaration is JetClass) { - if (modifierList == declaration.getPrimaryConstructorModifierList()) { - descriptor = (descriptor as ClassDescriptor).getUnsubstitutedPrimaryConstructor() - ?: error("No constructor found: ${declaration.getText()}") - } - } - - if (declaration is JetClassOrObject && modifierList.getParent() == declaration.getBody() && descriptor is LazyClassDescriptor) { - return descriptor.getDanglingAnnotations() - } - - return descriptor.getAnnotations() - } - - private fun typeParameterAdditionalResolve(analyzer: KotlinCodeAnalyzer, typeParameter: JetTypeParameter): BindingTrace { - val descriptor = analyzer.resolveToDescriptor(typeParameter) - ForceResolveUtil.forceResolveAllContents(descriptor) - - return resolveSession.getTrace() - } - - private fun delegationSpecifierAdditionalResolve(resolveSession: ResolveSession, jetElement: JetElement, classOrObject: JetClassOrObject, file: JetFile): BindingTrace { - val trace = createDelegatingTrace(jetElement) - val descriptor = resolveSession.resolveToDescriptor(classOrObject) as LazyClassDescriptor - - // Activate resolving of supertypes - ForceResolveUtil.forceResolveAllContents(descriptor.getTypeConstructor().getSupertypes()) - - val bodyResolver = createBodyResolver(resolveSession, trace, file, StatementFilter.NONE) - bodyResolver.resolveDelegationSpecifierList(DataFlowInfo.EMPTY, - classOrObject, - descriptor, - descriptor.getUnsubstitutedPrimaryConstructor(), - descriptor.getScopeForClassHeaderResolution(), - descriptor.getScopeForMemberDeclarationResolution()) - - return trace - } - - private fun propertyAdditionalResolve(resolveSession: ResolveSession, jetProperty: JetProperty, file: JetFile, statementFilter: StatementFilter): BindingTrace { - val trace = createDelegatingTrace(jetProperty) - val propertyResolutionScope = resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(jetProperty) - - val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) - val descriptor = resolveSession.resolveToDescriptor(jetProperty) as PropertyDescriptor - ForceResolveUtil.forceResolveAllContents(descriptor) - - val propertyInitializer = jetProperty.getInitializer() - if (propertyInitializer != null) { - bodyResolver.resolvePropertyInitializer(DataFlowInfo.EMPTY, jetProperty, descriptor, propertyInitializer, propertyResolutionScope) - } - - val propertyDelegate = jetProperty.getDelegateExpression() - if (propertyDelegate != null) { - bodyResolver.resolvePropertyDelegate(DataFlowInfo.EMPTY, jetProperty, descriptor, propertyDelegate, propertyResolutionScope, propertyResolutionScope) - } - - val bodyResolveContext = BodyResolveContextForLazy(TopDownAnalysisMode.LocalDeclarations, { declaration -> - assert(declaration.getParent() == jetProperty) { "Must be called only for property accessors, but called for $declaration" } - resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(declaration) - }) - - bodyResolver.resolvePropertyAccessors(bodyResolveContext, jetProperty, descriptor) - - for (accessor in jetProperty.getAccessors()) { - JetFlowInformationProvider(accessor, trace).checkDeclaration() - } - - return trace - } - - private fun functionAdditionalResolve(resolveSession: ResolveSession, namedFunction: JetNamedFunction, file: JetFile, statementFilter: StatementFilter): BindingTrace { - val trace = createDelegatingTrace(namedFunction) - - val scope = resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(namedFunction) - val functionDescriptor = resolveSession.resolveToDescriptor(namedFunction) as FunctionDescriptor - ForceResolveUtil.forceResolveAllContents(functionDescriptor) - - val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) - bodyResolver.resolveFunctionBody(DataFlowInfo.EMPTY, trace, namedFunction, functionDescriptor, scope) - - return trace - } - - private fun secondaryConstructorAdditionalResolve(resolveSession: ResolveSession, constructor: JetSecondaryConstructor, file: JetFile, statementFilter: StatementFilter): BindingTrace { - val trace = createDelegatingTrace(constructor) - - val scope = resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(constructor) - val constructorDescriptor = resolveSession.resolveToDescriptor(constructor) as ConstructorDescriptor - ForceResolveUtil.forceResolveAllContents(constructorDescriptor) - - val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) - bodyResolver.resolveSecondaryConstructorBody(DataFlowInfo.EMPTY, trace, constructor, constructorDescriptor, scope) - - return trace - } - - private fun constructorAdditionalResolve(resolveSession: ResolveSession, klass: JetClass, file: JetFile): BindingTrace { - val trace = createDelegatingTrace(klass) - val scope = resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(klass) - - val classDescriptor = resolveSession.resolveToDescriptor(klass) as ClassDescriptor - val constructorDescriptor = classDescriptor.getUnsubstitutedPrimaryConstructor() - ?: error("Can't get primary constructor for descriptor '$classDescriptor' in from class '${klass.getElementTextWithContext()}'") - - val bodyResolver = createBodyResolver(resolveSession, trace, file, StatementFilter.NONE) - bodyResolver.resolveConstructorParameterDefaultValuesAndAnnotations(DataFlowInfo.EMPTY, trace, klass, constructorDescriptor, scope) - - return trace - } - - private fun initializerAdditionalResolve(resolveSession: ResolveSession, classInitializer: JetClassInitializer, file: JetFile, statementFilter: StatementFilter): BindingTrace { - val trace = createDelegatingTrace(classInitializer) - - val classOrObject = classInitializer.getParentOfType(true)!! - val classOrObjectDescriptor = resolveSession.resolveToDescriptor(classOrObject) as LazyClassDescriptor - - val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) - bodyResolver.resolveAnonymousInitializer(DataFlowInfo.EMPTY, classInitializer, classOrObjectDescriptor) - - return trace - } - - private fun createBodyResolver( - resolveSession: ResolveSession, - trace: BindingTrace, - file: JetFile, - statementFilter: StatementFilter - ): BodyResolver { - val globalContext = SimpleGlobalContext(resolveSession.getStorageManager(), resolveSession.getExceptionTracker()) - val module = resolveSession.getModuleDescriptor() - return createContainerForBodyResolve( - globalContext.withProject(file.getProject()).withModule(module), - trace, - getTargetPlatform(file), - statementFilter - ).get() - } - - // All additional resolve should be done to separate trace - private fun createDelegatingTrace(resolveElement: JetElement): BindingTrace { - return resolveSession.getStorageManager().createSafeTrace( - DelegatingBindingTrace(resolveSession.getBindingContext(), "trace to resolve element", resolveElement)) - } - - protected abstract fun getTargetPlatform(file: JetFile): TargetPlatform - - private class BodyResolveContextForLazy( - private val topDownAnalysisMode: TopDownAnalysisMode, - private val declaringScopes: Function1 - ) : BodiesResolveContext { - override fun getFiles(): Collection = setOf() - - override fun getDeclaredClasses(): MutableMap = hashMapOf() - - override fun getAnonymousInitializers(): MutableMap = hashMapOf() - - override fun getSecondaryConstructors(): MutableMap = hashMapOf() - - override fun getProperties(): MutableMap = hashMapOf() - - override fun getFunctions(): MutableMap = hashMapOf() - - override fun getDeclaringScope(declaration: JetDeclaration): JetScope? = declaringScopes(declaration) - - override fun getScripts(): MutableMap = hashMapOf() - - override fun getOuterDataFlowInfo(): DataFlowInfo = DataFlowInfo.EMPTY - - override fun getTopDownAnalysisMode() = topDownAnalysisMode - } -} - diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt index c93752b0177..33a1e1b11e3 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt @@ -22,18 +22,38 @@ import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.PsiModificationTracker import com.intellij.util.containers.ContainerUtil +import org.jetbrains.kotlin.analyzer.computeTypeInContext import org.jetbrains.kotlin.asJava.KotlinCodeBlockModificationListener +import org.jetbrains.kotlin.cfg.JetFlowInformationProvider +import org.jetbrains.kotlin.container.get +import org.jetbrains.kotlin.context.SimpleGlobalContext +import org.jetbrains.kotlin.context.withModule +import org.jetbrains.kotlin.context.withProject +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.frontend.di.createContainerForBodyResolve import org.jetbrains.kotlin.idea.stubindex.JetProbablyNothingFunctionShortNameIndex import org.jetbrains.kotlin.idea.stubindex.JetProbablyNothingPropertyShortNameIndex +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.BodyResolveCache -import org.jetbrains.kotlin.resolve.StatementFilter -import org.jetbrains.kotlin.resolve.TargetPlatform +import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.resolve.* +import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.lazy.* +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.resolve.util.getScopeAndDataFlowForAnalyzeFragment +import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.utils.addToStdlib.check +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull -public class ResolveElementCache(resolveSession: ResolveSession, private val project: Project) : ElementResolver(resolveSession), BodyResolveCache { +public class ResolveElementCache( + private val resolveSession: ResolveSession, + private val project: Project +) : BodyResolveCache { private class CachedFullResolve(val bindingContext: BindingContext, resolveElement: JetElement) { private val modificationStamp: Long? = modificationStamp(resolveElement) @@ -84,7 +104,21 @@ public class ResolveElementCache(resolveSession: ResolveSession, private val pro }, false) - override fun getElementAdditionalResolve(resolveElement: JetElement, contextElement: JetElement, bodyResolveMode: BodyResolveMode): BindingContext { + + private fun getTargetPlatform(file: JetFile): TargetPlatform = TargetPlatformDetector.getPlatform(file) + + private fun probablyNothingCallableNames(): ProbablyNothingCallableNames { + return object : ProbablyNothingCallableNames { + override fun functionNames() = JetProbablyNothingFunctionShortNameIndex.getInstance().getAllKeys(project) + override fun propertyNames() = JetProbablyNothingPropertyShortNameIndex.getInstance().getAllKeys(project) + } + } + + override fun resolveFunctionBody(function: JetNamedFunction) + = getElementAdditionalResolve(function, function, BodyResolveMode.FULL) + + + fun getElementAdditionalResolve(resolveElement: JetElement, contextElement: JetElement, bodyResolveMode: BodyResolveMode): BindingContext { // check if full additional resolve already performed and is up-to-date val fullResolveMap = fullResolveCache.value val cachedFullResolve = fullResolveMap[resolveElement] @@ -146,16 +180,380 @@ public class ResolveElementCache(resolveSession: ResolveSession, private val pro } } - override fun getTargetPlatform(file: JetFile): TargetPlatform = TargetPlatformDetector.getPlatform(file) + public fun resolveToElement(element: JetElement, bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext { + var contextElement = element - override fun probablyNothingCallableNames(): ProbablyNothingCallableNames { - return object : ProbablyNothingCallableNames { - override fun functionNames() = JetProbablyNothingFunctionShortNameIndex.getInstance().getAllKeys(project) - override fun propertyNames() = JetProbablyNothingPropertyShortNameIndex.getInstance().getAllKeys(project) + val elementOfAdditionalResolve = findElementOfAdditionalResolve(contextElement) + + if (elementOfAdditionalResolve is JetParameter) { + // Parameters for function literal could be met inside other parameters. We can't make resolveToDescriptors for internal elements. + contextElement = elementOfAdditionalResolve + } + else if (elementOfAdditionalResolve != null) { + return getElementAdditionalResolve(elementOfAdditionalResolve, contextElement, bodyResolveMode) + } + + val declaration = contextElement.getParentOfType(false) + if (declaration != null && declaration !is JetClassInitializer) { + // Activate descriptor resolution + resolveSession.resolveToDescriptor(declaration) + } + + return resolveSession.getBindingContext() + } + + private fun findElementOfAdditionalResolve(element: JetElement): JetElement? { + val elementOfAdditionalResolve = JetPsiUtil.getTopmostParentOfTypes( + element, + javaClass(), + javaClass(), + javaClass(), + javaClass(), + javaClass(), + javaClass(), + javaClass(), + javaClass(), + javaClass(), + javaClass(), + javaClass(), + javaClass(), + javaClass()) as JetElement? + + when (elementOfAdditionalResolve) { + null -> { + // Case of JetAnnotationEntry on top level class + if (element is JetAnnotationEntry) { + return element + } + + return null + } + + is JetPackageDirective -> return element + + is JetParameter -> { + val klass = elementOfAdditionalResolve.getParentOfType(strict = true) + if (klass != null && elementOfAdditionalResolve.getParent() == klass.getPrimaryConstructorParameterList()) { + return klass + } + + return elementOfAdditionalResolve + } + + else -> return elementOfAdditionalResolve } } - override fun resolveFunctionBody(function: JetNamedFunction) - = getElementAdditionalResolve(function, function, BodyResolveMode.FULL) + private fun performElementAdditionalResolve(resolveElement: JetElement, contextElement: JetElement, bodyResolveMode: BodyResolveMode): Pair { + val file = resolveElement.getContainingJetFile() + + var statementFilterUsed = StatementFilter.NONE + + fun createStatementFilter(): StatementFilter { + assert(resolveElement is JetDeclaration) + if (bodyResolveMode != BodyResolveMode.FULL) { + statementFilterUsed = PartialBodyResolveFilter( + contextElement, + resolveElement as JetDeclaration, + probablyNothingCallableNames(), + bodyResolveMode == BodyResolveMode.PARTIAL_FOR_COMPLETION) + } + return statementFilterUsed + } + + val trace: BindingTrace = when (resolveElement) { + is JetNamedFunction -> functionAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter()) + + is JetClassInitializer -> initializerAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter()) + + is JetSecondaryConstructor -> secondaryConstructorAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter()) + + is JetProperty -> propertyAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter()) + + is JetDelegationSpecifierList -> delegationSpecifierAdditionalResolve(resolveSession, resolveElement, resolveElement.getParent() as JetClassOrObject, file) + + is JetInitializerList -> delegationSpecifierAdditionalResolve(resolveSession, resolveElement, resolveElement.getParent() as JetEnumEntry, file) + + is JetImportList -> { + val scope = resolveSession.getFileScopeProvider().getFileScope(resolveElement.getContainingJetFile()) + scope.forceResolveAllImports() + resolveSession.getTrace() + } + + is JetAnnotationEntry -> annotationAdditionalResolve(resolveSession, resolveElement) + + is JetClass -> constructorAdditionalResolve(resolveSession, resolveElement, file) + + is JetTypeParameter -> typeParameterAdditionalResolve(resolveSession, resolveElement) + + is JetTypeConstraint -> typeConstraintAdditionalResolve(resolveSession, resolveElement) + + is JetCodeFragment -> codeFragmentAdditionalResolve(resolveSession, resolveElement, bodyResolveMode) + + else -> { + if (resolveElement.getParentOfType(true) != null) { + packageRefAdditionalResolve(resolveSession, resolveElement) + } + else { + error("Invalid type of the topmost parent: $resolveElement\n${resolveElement.getElementTextWithContext()}") + } + } + } + + val controlFlowTrace = DelegatingBindingTrace(trace.getBindingContext(), "Element control flow resolve", resolveElement) + JetFlowInformationProvider(resolveElement, controlFlowTrace).checkDeclaration() + controlFlowTrace.addOwnDataTo(trace, null, false) + + return Pair(trace.getBindingContext(), statementFilterUsed) + } + + private fun packageRefAdditionalResolve(resolveSession: ResolveSession, jetElement: JetElement): BindingTrace { + val trace = createDelegatingTrace(jetElement) + + if (jetElement is JetSimpleNameExpression) { + val header = jetElement.getParentOfType(true)!! + + if (trace.getBindingContext()[BindingContext.RESOLUTION_SCOPE, jetElement] == null) { + val scope = resolveSession.getModuleDescriptor().getPackage(header.getFqName(jetElement).parent()).memberScope + trace.record(BindingContext.RESOLUTION_SCOPE, jetElement, scope) + } + + if (Name.isValidIdentifier(jetElement.getReferencedName())) { + if (trace.getBindingContext()[BindingContext.REFERENCE_TARGET, jetElement] == null) { + val fqName = header.getFqName(jetElement) + val packageDescriptor = resolveSession.getModuleDescriptor().getPackage(fqName) + trace.record(BindingContext.REFERENCE_TARGET, jetElement, packageDescriptor) + } + } + } + + return trace + } + + private fun typeConstraintAdditionalResolve(analyzer: KotlinCodeAnalyzer, jetTypeConstraint: JetTypeConstraint): BindingTrace { + val declaration = jetTypeConstraint.getParentOfType(true)!! + val descriptor = analyzer.resolveToDescriptor(declaration) as ClassDescriptor + + for (parameterDescriptor in descriptor.getTypeConstructor().getParameters()) { + ForceResolveUtil.forceResolveAllContents(parameterDescriptor) + } + + return resolveSession.getTrace() + } + + private fun codeFragmentAdditionalResolve(resolveSession: ResolveSession, codeFragment: JetCodeFragment, bodyResolveMode: BodyResolveMode): BindingTrace { + val trace = createDelegatingTrace(codeFragment) + + val codeFragmentExpression = codeFragment.getContentElement() as? JetExpression ?: return trace + + val (scopeForContextElement, dataFlowInfoForContextElement) = codeFragment.getScopeAndDataFlowForAnalyzeFragment(resolveSession) { + val contextResolveMode = if (bodyResolveMode == BodyResolveMode.PARTIAL) + BodyResolveMode.PARTIAL_FOR_COMPLETION + else + bodyResolveMode + + resolveToElement(it, contextResolveMode) + } ?: return trace + + codeFragmentExpression.computeTypeInContext(scopeForContextElement, trace, dataFlowInfoForContextElement, + TypeUtils.NO_EXPECTED_TYPE, resolveSession.getModuleDescriptor()) + + return trace + } + + private fun annotationAdditionalResolve(resolveSession: ResolveSession, jetAnnotationEntry: JetAnnotationEntry): BindingTrace { + val modifierList = jetAnnotationEntry.getParentOfType(true) + val declaration = modifierList?.getParentOfType(true) + if (declaration != null) { + doResolveAnnotations(getAnnotationsByDeclaration(resolveSession, modifierList!!, declaration)) + } + else { + val fileAnnotationList = jetAnnotationEntry.getParentOfType(true) + if (fileAnnotationList != null) { + doResolveAnnotations(resolveSession.getFileAnnotations(fileAnnotationList.getContainingJetFile())) + } + if (modifierList != null && modifierList.getParent() is JetFile) { + doResolveAnnotations(resolveSession.getDanglingAnnotations(modifierList.getContainingJetFile())) + } + } + + return resolveSession.getTrace() + } + + private fun doResolveAnnotations(annotations: Annotations) { + ForceResolveUtil.forceResolveAllContents(annotations) + } + + private fun getAnnotationsByDeclaration(resolveSession: ResolveSession, modifierList: JetModifierList, declaration: JetDeclaration): Annotations { + var descriptor = resolveSession.resolveToDescriptor(declaration) + if (declaration is JetClass) { + if (modifierList == declaration.getPrimaryConstructorModifierList()) { + descriptor = (descriptor as ClassDescriptor).getUnsubstitutedPrimaryConstructor() + ?: error("No constructor found: ${declaration.getText()}") + } + } + + if (declaration is JetClassOrObject && modifierList.getParent() == declaration.getBody() && descriptor is LazyClassDescriptor) { + return descriptor.getDanglingAnnotations() + } + + return descriptor.getAnnotations() + } + + private fun typeParameterAdditionalResolve(analyzer: KotlinCodeAnalyzer, typeParameter: JetTypeParameter): BindingTrace { + val descriptor = analyzer.resolveToDescriptor(typeParameter) + ForceResolveUtil.forceResolveAllContents(descriptor) + + return resolveSession.getTrace() + } + + private fun delegationSpecifierAdditionalResolve(resolveSession: ResolveSession, jetElement: JetElement, classOrObject: JetClassOrObject, file: JetFile): BindingTrace { + val trace = createDelegatingTrace(jetElement) + val descriptor = resolveSession.resolveToDescriptor(classOrObject) as LazyClassDescriptor + + // Activate resolving of supertypes + ForceResolveUtil.forceResolveAllContents(descriptor.getTypeConstructor().getSupertypes()) + + val bodyResolver = createBodyResolver(resolveSession, trace, file, StatementFilter.NONE) + bodyResolver.resolveDelegationSpecifierList(DataFlowInfo.EMPTY, + classOrObject, + descriptor, + descriptor.getUnsubstitutedPrimaryConstructor(), + descriptor.getScopeForClassHeaderResolution(), + descriptor.getScopeForMemberDeclarationResolution()) + + return trace + } + + private fun propertyAdditionalResolve(resolveSession: ResolveSession, jetProperty: JetProperty, file: JetFile, statementFilter: StatementFilter): BindingTrace { + val trace = createDelegatingTrace(jetProperty) + val propertyResolutionScope = resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(jetProperty) + + val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) + val descriptor = resolveSession.resolveToDescriptor(jetProperty) as PropertyDescriptor + ForceResolveUtil.forceResolveAllContents(descriptor) + + val propertyInitializer = jetProperty.getInitializer() + if (propertyInitializer != null) { + bodyResolver.resolvePropertyInitializer(DataFlowInfo.EMPTY, jetProperty, descriptor, propertyInitializer, propertyResolutionScope) + } + + val propertyDelegate = jetProperty.getDelegateExpression() + if (propertyDelegate != null) { + bodyResolver.resolvePropertyDelegate(DataFlowInfo.EMPTY, jetProperty, descriptor, propertyDelegate, propertyResolutionScope, propertyResolutionScope) + } + + val bodyResolveContext = BodyResolveContextForLazy(TopDownAnalysisMode.LocalDeclarations, { declaration -> + assert(declaration.getParent() == jetProperty) { "Must be called only for property accessors, but called for $declaration" } + resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(declaration) + }) + + bodyResolver.resolvePropertyAccessors(bodyResolveContext, jetProperty, descriptor) + + for (accessor in jetProperty.getAccessors()) { + JetFlowInformationProvider(accessor, trace).checkDeclaration() + } + + return trace + } + + private fun functionAdditionalResolve(resolveSession: ResolveSession, namedFunction: JetNamedFunction, file: JetFile, statementFilter: StatementFilter): BindingTrace { + val trace = createDelegatingTrace(namedFunction) + + val scope = resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(namedFunction) + val functionDescriptor = resolveSession.resolveToDescriptor(namedFunction) as FunctionDescriptor + ForceResolveUtil.forceResolveAllContents(functionDescriptor) + + val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) + bodyResolver.resolveFunctionBody(DataFlowInfo.EMPTY, trace, namedFunction, functionDescriptor, scope) + + return trace + } + + private fun secondaryConstructorAdditionalResolve(resolveSession: ResolveSession, constructor: JetSecondaryConstructor, file: JetFile, statementFilter: StatementFilter): BindingTrace { + val trace = createDelegatingTrace(constructor) + + val scope = resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(constructor) + val constructorDescriptor = resolveSession.resolveToDescriptor(constructor) as ConstructorDescriptor + ForceResolveUtil.forceResolveAllContents(constructorDescriptor) + + val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) + bodyResolver.resolveSecondaryConstructorBody(DataFlowInfo.EMPTY, trace, constructor, constructorDescriptor, scope) + + return trace + } + + private fun constructorAdditionalResolve(resolveSession: ResolveSession, klass: JetClass, file: JetFile): BindingTrace { + val trace = createDelegatingTrace(klass) + val scope = resolveSession.getDeclarationScopeProvider().getResolutionScopeForDeclaration(klass) + + val classDescriptor = resolveSession.resolveToDescriptor(klass) as ClassDescriptor + val constructorDescriptor = classDescriptor.getUnsubstitutedPrimaryConstructor() + ?: error("Can't get primary constructor for descriptor '$classDescriptor' in from class '${klass.getElementTextWithContext()}'") + + val bodyResolver = createBodyResolver(resolveSession, trace, file, StatementFilter.NONE) + bodyResolver.resolveConstructorParameterDefaultValuesAndAnnotations(DataFlowInfo.EMPTY, trace, klass, constructorDescriptor, scope) + + return trace + } + + private fun initializerAdditionalResolve(resolveSession: ResolveSession, classInitializer: JetClassInitializer, file: JetFile, statementFilter: StatementFilter): BindingTrace { + val trace = createDelegatingTrace(classInitializer) + + val classOrObject = classInitializer.getParentOfType(true)!! + val classOrObjectDescriptor = resolveSession.resolveToDescriptor(classOrObject) as LazyClassDescriptor + + val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) + bodyResolver.resolveAnonymousInitializer(DataFlowInfo.EMPTY, classInitializer, classOrObjectDescriptor) + + return trace + } + + private fun createBodyResolver( + resolveSession: ResolveSession, + trace: BindingTrace, + file: JetFile, + statementFilter: StatementFilter + ): BodyResolver { + val globalContext = SimpleGlobalContext(resolveSession.getStorageManager(), resolveSession.getExceptionTracker()) + val module = resolveSession.getModuleDescriptor() + return createContainerForBodyResolve( + globalContext.withProject(file.getProject()).withModule(module), + trace, + getTargetPlatform(file), + statementFilter + ).get() + } + + // All additional resolve should be done to separate trace + private fun createDelegatingTrace(resolveElement: JetElement): BindingTrace { + return resolveSession.getStorageManager().createSafeTrace( + DelegatingBindingTrace(resolveSession.getBindingContext(), "trace to resolve element", resolveElement)) + } + + private class BodyResolveContextForLazy( + private val topDownAnalysisMode: TopDownAnalysisMode, + private val declaringScopes: Function1 + ) : BodiesResolveContext { + override fun getFiles(): Collection = setOf() + + override fun getDeclaredClasses(): MutableMap = hashMapOf() + + override fun getAnonymousInitializers(): MutableMap = hashMapOf() + + override fun getSecondaryConstructors(): MutableMap = hashMapOf() + + override fun getProperties(): MutableMap = hashMapOf() + + override fun getFunctions(): MutableMap = hashMapOf() + + override fun getDeclaringScope(declaration: JetDeclaration): JetScope? = declaringScopes(declaration) + + override fun getScripts(): MutableMap = hashMapOf() + + override fun getOuterDataFlowInfo(): DataFlowInfo = DataFlowInfo.EMPTY + + override fun getTopDownAnalysisMode() = topDownAnalysisMode + } }