From ccbb015606843de50e0b8739a446b265871a624c Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Thu, 8 Oct 2015 17:05:22 +0300 Subject: [PATCH] Completion for evaluate expression: add only imports from code fragment to scope when analyzing it --- .../kotlin/resolve/scopes/utils/ScopeUtils.kt | 23 +++++++++++++++- .../idea/util/ShadowedDeclarationsFilter.kt | 1 + .../jetbrains/kotlin/idea/util/scopeUtils.kt | 22 --------------- .../caches/resolve/CodeFragmentAnalyzer.kt | 27 ++++++++++++------- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt index 9950290a265..9d7bd94d3c6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt @@ -90,7 +90,10 @@ public fun LexicalScope.getDescriptorsFiltered( @Deprecated("Use getOwnProperties instead") public fun LexicalScope.getLocalVariable(name: Name): VariableDescriptor? { processForMeAndParent { - if (it is LazyFileScope) { + if (it is LexicalScopeWrapper) { + return it.delegate.getLocalVariable(name) + } + else if (it is LazyFileScope) { return it.getLocalVariable(name) // todo: remove hack for repl interpreter } else if (it is MemberScopeToFileScopeAdapter) { // todo remove hack @@ -273,3 +276,21 @@ internal inline fun LexicalScope.collectAllFromMeAndParent( processForMeAndParent { result = result.concat(collect(it)) } return result ?: emptySet() } + +public fun LexicalScope.addImportScope(importScope: JetScope): LexicalScope { + val fileScope = getFileScope() + val scopeWithAdditionImport = + LexicalChainedScope(fileScope, fileScope.ownerDescriptor, false, null, "Scope with addition import", importScope) + return LexicalScopeWrapper(this, scopeWithAdditionImport) +} + +private class LexicalScopeWrapper(val delegate: LexicalScope, val fileScopeReplace: LexicalScope): LexicalScope by delegate { + override val parent: LexicalScope? by lazy(LazyThreadSafetyMode.NONE) { + if (delegate is FileScope) { + fileScopeReplace + } + else { + LexicalScopeWrapper(delegate.parent!!, fileScopeReplace) + } + } +} diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt index 313f4582a4f..b7d51892ac7 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/ShadowedDeclarationsFilter.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.scopes.ExplicitImportsScope import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.resolve.scopes.utils.addImportScope import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.util.descriptorsEqualWithSubstitution import java.util.* diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/scopeUtils.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/scopeUtils.kt index a9c784b75e7..479da690261 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/scopeUtils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/scopeUtils.kt @@ -22,11 +22,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.scopes.FileScope import org.jetbrains.kotlin.resolve.scopes.JetScope -import org.jetbrains.kotlin.resolve.scopes.LexicalChainedScope -import org.jetbrains.kotlin.resolve.scopes.LexicalScope -import org.jetbrains.kotlin.resolve.scopes.utils.getFileScope public fun JetScope.getAllAccessibleVariables(name: Name): Collection @@ -45,22 +41,4 @@ public fun JetScope.getVariableFromImplicitReceivers(name: Name): VariableDescri it.type.memberScope.getProperties(name, NoLookupLocation.FROM_IDE).singleOrNull()?.let { return it } } return null -} - -public fun LexicalScope.addImportScope(importScope: JetScope): LexicalScope { - val fileScope = getFileScope() - val scopeWithAdditionImport = - LexicalChainedScope(fileScope, fileScope.ownerDescriptor, false, null, "Scope with addition import", importScope) - return LexicalScopeWrapper(this, scopeWithAdditionImport) -} - -private class LexicalScopeWrapper(val delegate: LexicalScope, val fileScopeReplace: LexicalScope): LexicalScope by delegate { - override val parent: LexicalScope? by lazy(LazyThreadSafetyMode.NONE) { - if (delegate is FileScope) { - fileScopeReplace - } - else { - LexicalScopeWrapper(delegate.parent!!, fileScopeReplace) - } - } } \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/CodeFragmentAnalyzer.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/CodeFragmentAnalyzer.kt index da92ea12a3c..d272255dba2 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/CodeFragmentAnalyzer.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/CodeFragmentAnalyzer.kt @@ -24,13 +24,14 @@ import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.psi.psiUtil.siblings import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.ResolveSession -import org.jetbrains.kotlin.resolve.scopes.JetScope -import org.jetbrains.kotlin.resolve.scopes.LexicalChainedScope +import org.jetbrains.kotlin.resolve.scopes.ChainedScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope +import org.jetbrains.kotlin.resolve.scopes.utils.addImportScope import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull @@ -38,6 +39,7 @@ import javax.inject.Inject public class CodeFragmentAnalyzer( private val resolveSession: ResolveSession, + private val qualifierResolver: QualifiedExpressionResolver, private val expressionTypingServices: ExpressionTypingServices ) { @@ -130,13 +132,20 @@ public class CodeFragmentAnalyzer( if (scopeForContextElement == null) return null - val codeFragmentScope = resolveSession.getFileScopeProvider().getFileScope(codeFragment) - val chainedScope = LexicalChainedScope( - scopeForContextElement, scopeForContextElement.ownerDescriptor, - false, null, - "Scope for resolve code fragment", - codeFragmentScope) + val importList = codeFragment.importsAsImportList() + if (importList == null || importList.imports.isEmpty()) { + return scopeForContextElement to dataFlowInfo + } - return chainedScope to dataFlowInfo + val importScopes = importList.imports.map { + qualifierResolver.processImportReference(it, resolveSession.moduleDescriptor, resolveSession.trace, null) + }.filterNotNull() + + val chainedScope = ChainedScope( + scopeForContextElement.ownerDescriptor, + "Scope for resolve code fragment", + *importScopes.toTypedArray()) + + return scopeForContextElement.addImportScope(chainedScope) to dataFlowInfo } }