Refactoring: move similar part for obtaining scope for codeFragment to JetCodeFragment
This commit is contained in:
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.context.withProject
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.frontend.di.createContainerForBodyResolve
|
import org.jetbrains.kotlin.frontend.di.createContainerForBodyResolve
|
||||||
|
import org.jetbrains.kotlin.resolve.util.getScopeAndDataFlowForAnalyzeFragment
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -206,53 +207,22 @@ public abstract class ElementResolver protected constructor(
|
|||||||
val trace = createDelegatingTrace(codeFragment)
|
val trace = createDelegatingTrace(codeFragment)
|
||||||
|
|
||||||
val codeFragmentExpression = codeFragment.getContentElement() as? JetExpression ?: return trace
|
val codeFragmentExpression = codeFragment.getContentElement() as? JetExpression ?: return trace
|
||||||
val contextElement = codeFragment.correctedContext
|
|
||||||
|
|
||||||
val scopeForContextElement: JetScope?
|
val (scopeForContextElement, dataFlowInfoForContextElement) = codeFragment.getScopeAndDataFlowForAnalyzeFragment(resolveSession) {
|
||||||
val dataFlowInfoForContextElement: DataFlowInfo
|
val contextResolveMode = if (bodyResolveMode == BodyResolveMode.PARTIAL)
|
||||||
when (contextElement) {
|
BodyResolveMode.PARTIAL_FOR_COMPLETION
|
||||||
is JetClassOrObject -> {
|
else
|
||||||
val descriptor = resolveSession.resolveToDescriptor(contextElement) as LazyClassDescriptor
|
bodyResolveMode
|
||||||
scopeForContextElement = descriptor.getScopeForMemberDeclarationResolution()
|
|
||||||
dataFlowInfoForContextElement = DataFlowInfo.EMPTY
|
|
||||||
}
|
|
||||||
|
|
||||||
is JetExpression -> {
|
resolveToElement(it, contextResolveMode)
|
||||||
// do not use PARTIAL body resolve mode because because it does not know about names used in our fragment
|
} ?: return trace
|
||||||
val contextResolveMode = if (bodyResolveMode == BodyResolveMode.PARTIAL)
|
|
||||||
BodyResolveMode.PARTIAL_FOR_COMPLETION
|
|
||||||
else
|
|
||||||
bodyResolveMode
|
|
||||||
val contextForElement = resolveToElement(contextElement, contextResolveMode)
|
|
||||||
scopeForContextElement = contextForElement[BindingContext.RESOLUTION_SCOPE, contextElement]
|
|
||||||
dataFlowInfoForContextElement = contextForElement.getDataFlowInfo(contextElement)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> return trace
|
codeFragmentExpression.computeTypeInContext(scopeForContextElement, trace, dataFlowInfoForContextElement,
|
||||||
}
|
|
||||||
|
|
||||||
if (scopeForContextElement == null) return trace
|
|
||||||
|
|
||||||
val codeFragmentScope = resolveSession.getFileScopeProvider().getFileScope(codeFragment)
|
|
||||||
val chainedScope = ChainedScope(scopeForContextElement.getContainingDeclaration(),
|
|
||||||
"Scope for resolve code fragment", scopeForContextElement, codeFragmentScope)
|
|
||||||
|
|
||||||
codeFragmentExpression.computeTypeInContext(chainedScope, trace, dataFlowInfoForContextElement,
|
|
||||||
TypeUtils.NO_EXPECTED_TYPE, resolveSession.getModuleDescriptor())
|
TypeUtils.NO_EXPECTED_TYPE, resolveSession.getModuleDescriptor())
|
||||||
|
|
||||||
return trace
|
return trace
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: this code should be moved into debugger which should set correct context for its code fragment
|
|
||||||
private val JetCodeFragment.correctedContext: PsiElement?
|
|
||||||
get() {
|
|
||||||
val context = getContext()
|
|
||||||
if (context is JetBlockExpression) {
|
|
||||||
return context.getStatements().lastOrNull() ?: context
|
|
||||||
}
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun annotationAdditionalResolve(resolveSession: ResolveSession, jetAnnotationEntry: JetAnnotationEntry): BindingTrace {
|
private fun annotationAdditionalResolve(resolveSession: ResolveSession, jetAnnotationEntry: JetAnnotationEntry): BindingTrace {
|
||||||
val modifierList = jetAnnotationEntry.getParentOfType<JetModifierList>(true)
|
val modifierList = jetAnnotationEntry.getParentOfType<JetModifierList>(true)
|
||||||
val declaration = modifierList?.getParentOfType<JetDeclaration>(true)
|
val declaration = modifierList?.getParentOfType<JetDeclaration>(true)
|
||||||
@@ -397,7 +367,7 @@ public abstract class ElementResolver protected constructor(
|
|||||||
|
|
||||||
val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter)
|
val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter)
|
||||||
bodyResolver.resolveAnonymousInitializer(DataFlowInfo.EMPTY, classInitializer, classOrObjectDescriptor)
|
bodyResolver.resolveAnonymousInitializer(DataFlowInfo.EMPTY, classInitializer, classOrObjectDescriptor)
|
||||||
|
|
||||||
return trace
|
return trace
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* 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.util
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
|
|
||||||
|
//TODO: this code should be moved into debugger which should set correct context for its code fragment
|
||||||
|
private fun correctContext(oldContext: PsiElement?): PsiElement? {
|
||||||
|
if (oldContext is JetBlockExpression) {
|
||||||
|
return oldContext.getStatements().lastOrNull() ?: oldContext
|
||||||
|
}
|
||||||
|
return oldContext
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun JetCodeFragment.getScopeAndDataFlowForAnalyzeFragment(
|
||||||
|
resolveSession: KotlinCodeAnalyzer,
|
||||||
|
resolveToElement: (JetElement) -> BindingContext
|
||||||
|
): Pair<JetScope, DataFlowInfo>? {
|
||||||
|
val context = correctContext(getContext())
|
||||||
|
if (context !is JetExpression) return null
|
||||||
|
|
||||||
|
val scopeForContextElement: JetScope?
|
||||||
|
val dataFlowInfo: DataFlowInfo
|
||||||
|
|
||||||
|
when (context) {
|
||||||
|
is JetClassOrObject -> {
|
||||||
|
val descriptor = resolveSession.getClassDescriptor(context) as ClassDescriptorWithResolutionScopes
|
||||||
|
|
||||||
|
scopeForContextElement = descriptor.getScopeForMemberDeclarationResolution()
|
||||||
|
dataFlowInfo = DataFlowInfo.EMPTY
|
||||||
|
}
|
||||||
|
is JetExpression -> {
|
||||||
|
val contextForElement = resolveToElement(context)
|
||||||
|
|
||||||
|
scopeForContextElement = contextForElement[BindingContext.RESOLUTION_SCOPE, context]
|
||||||
|
dataFlowInfo = contextForElement.getDataFlowInfo(context)
|
||||||
|
}
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scopeForContextElement == null) return null
|
||||||
|
|
||||||
|
val codeFragmentScope = resolveSession.getFileScopeProvider().getFileScope(this)
|
||||||
|
val chainedScope = ChainedScope(
|
||||||
|
scopeForContextElement.getContainingDeclaration(),
|
||||||
|
"Scope for resolve code fragment",
|
||||||
|
scopeForContextElement, codeFragmentScope)
|
||||||
|
|
||||||
|
return chainedScope to dataFlowInfo
|
||||||
|
}
|
||||||
+5
-35
@@ -48,6 +48,7 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
|
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
|
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
|
import org.jetbrains.kotlin.resolve.util.getScopeAndDataFlowForAnalyzeFragment
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
|
|
||||||
@@ -270,44 +271,13 @@ private object KotlinResolveDataProvider {
|
|||||||
val codeFragmentExpression = codeFragment.getContentElement()
|
val codeFragmentExpression = codeFragment.getContentElement()
|
||||||
if (codeFragmentExpression !is JetExpression) return BindingContext.EMPTY
|
if (codeFragmentExpression !is JetExpression) return BindingContext.EMPTY
|
||||||
|
|
||||||
val contextElement = codeFragment.getContext()
|
val (scopeForContextElement, dataFlowInfo) = codeFragment.getScopeAndDataFlowForAnalyzeFragment(resolveSession) {
|
||||||
|
resolveSession.resolveToElement(it, BodyResolveMode.PARTIAL_FOR_COMPLETION) //TODO: discuss it
|
||||||
|
} ?: return BindingContext.EMPTY
|
||||||
|
|
||||||
val scopeForContextElement: JetScope?
|
|
||||||
val dataFlowInfo: DataFlowInfo
|
|
||||||
if (contextElement is JetClassOrObject) {
|
|
||||||
val descriptor = resolveSession.resolveToDescriptor(contextElement) as LazyClassDescriptor
|
|
||||||
|
|
||||||
scopeForContextElement = descriptor.getScopeForMemberDeclarationResolution()
|
|
||||||
dataFlowInfo = DataFlowInfo.EMPTY
|
|
||||||
}
|
|
||||||
else if (contextElement is JetBlockExpression) {
|
|
||||||
val newContextElement = contextElement.getStatements().lastOrNull()
|
|
||||||
if (newContextElement !is JetExpression) return BindingContext.EMPTY
|
|
||||||
|
|
||||||
val contextForElement = newContextElement.getResolutionFacade().analyze(newContextElement, BodyResolveMode.FULL)
|
|
||||||
|
|
||||||
scopeForContextElement = contextForElement[BindingContext.RESOLUTION_SCOPE, newContextElement]
|
|
||||||
dataFlowInfo = contextForElement.getDataFlowInfo(newContextElement)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (contextElement !is JetExpression) return BindingContext.EMPTY
|
|
||||||
|
|
||||||
val contextForElement = contextElement.getResolutionFacade().analyze(contextElement, BodyResolveMode.PARTIAL_FOR_COMPLETION) //TODO: discuss it
|
|
||||||
|
|
||||||
scopeForContextElement = contextForElement[BindingContext.RESOLUTION_SCOPE, contextElement]
|
|
||||||
dataFlowInfo = contextForElement.getDataFlowInfo(contextElement)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scopeForContextElement == null) return BindingContext.EMPTY
|
|
||||||
|
|
||||||
val codeFragmentScope = resolveSession.getFileScopeProvider().getFileScope(codeFragment)
|
|
||||||
val chainedScope = ChainedScope(
|
|
||||||
scopeForContextElement.getContainingDeclaration(),
|
|
||||||
"Scope for resolve code fragment",
|
|
||||||
scopeForContextElement, codeFragmentScope)
|
|
||||||
|
|
||||||
return codeFragmentExpression.analyzeInContext(
|
return codeFragmentExpression.analyzeInContext(
|
||||||
chainedScope,
|
scopeForContextElement,
|
||||||
BindingTraceContext(),
|
BindingTraceContext(),
|
||||||
dataFlowInfo,
|
dataFlowInfo,
|
||||||
TypeUtils.NO_EXPECTED_TYPE,
|
TypeUtils.NO_EXPECTED_TYPE,
|
||||||
|
|||||||
Reference in New Issue
Block a user