idea: cleanup code
This commit is contained in:
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.analysis
|
||||
@@ -37,15 +26,16 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
||||
import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
|
||||
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor
|
||||
|
||||
@JvmOverloads fun KtExpression.computeTypeInfoInContext(
|
||||
scope: LexicalScope,
|
||||
contextExpression: KtExpression = this,
|
||||
trace: BindingTrace = BindingTraceContext(),
|
||||
dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY,
|
||||
expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE,
|
||||
isStatement: Boolean = false,
|
||||
contextDependency: ContextDependency = ContextDependency.INDEPENDENT,
|
||||
expressionTypingServices: ExpressionTypingServices = contextExpression.getResolutionFacade().frontendService<ExpressionTypingServices>()
|
||||
@JvmOverloads
|
||||
fun KtExpression.computeTypeInfoInContext(
|
||||
scope: LexicalScope,
|
||||
contextExpression: KtExpression = this,
|
||||
trace: BindingTrace = BindingTraceContext(),
|
||||
dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY,
|
||||
expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE,
|
||||
isStatement: Boolean = false,
|
||||
contextDependency: ContextDependency = ContextDependency.INDEPENDENT,
|
||||
expressionTypingServices: ExpressionTypingServices = contextExpression.getResolutionFacade().frontendService<ExpressionTypingServices>()
|
||||
): KotlinTypeInfo {
|
||||
PreliminaryDeclarationVisitor.createForExpression(this, trace, expressionTypingServices.languageVersionSettings)
|
||||
return expressionTypingServices.getTypeInfo(
|
||||
@@ -53,52 +43,63 @@ import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor
|
||||
)
|
||||
}
|
||||
|
||||
@JvmOverloads fun KtExpression.analyzeInContext(
|
||||
scope: LexicalScope,
|
||||
contextExpression: KtExpression = this,
|
||||
trace: BindingTrace = BindingTraceContext(),
|
||||
dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY,
|
||||
expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE,
|
||||
isStatement: Boolean = false,
|
||||
contextDependency: ContextDependency = ContextDependency.INDEPENDENT,
|
||||
expressionTypingServices: ExpressionTypingServices = contextExpression.getResolutionFacade().frontendService<ExpressionTypingServices>()
|
||||
@JvmOverloads
|
||||
fun KtExpression.analyzeInContext(
|
||||
scope: LexicalScope,
|
||||
contextExpression: KtExpression = this,
|
||||
trace: BindingTrace = BindingTraceContext(),
|
||||
dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY,
|
||||
expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE,
|
||||
isStatement: Boolean = false,
|
||||
contextDependency: ContextDependency = ContextDependency.INDEPENDENT,
|
||||
expressionTypingServices: ExpressionTypingServices = contextExpression.getResolutionFacade().frontendService<ExpressionTypingServices>()
|
||||
): BindingContext {
|
||||
computeTypeInfoInContext(scope, contextExpression, trace, dataFlowInfo, expectedType, isStatement, contextDependency, expressionTypingServices)
|
||||
computeTypeInfoInContext(
|
||||
scope,
|
||||
contextExpression,
|
||||
trace,
|
||||
dataFlowInfo,
|
||||
expectedType,
|
||||
isStatement,
|
||||
contextDependency,
|
||||
expressionTypingServices
|
||||
)
|
||||
return trace.bindingContext
|
||||
}
|
||||
|
||||
@JvmOverloads fun KtExpression.computeTypeInContext(
|
||||
scope: LexicalScope,
|
||||
contextExpression: KtExpression = this,
|
||||
trace: BindingTrace = BindingTraceContext(),
|
||||
dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY,
|
||||
expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE
|
||||
): KotlinType? {
|
||||
return computeTypeInfoInContext(scope, contextExpression, trace, dataFlowInfo, expectedType).type
|
||||
}
|
||||
@JvmOverloads
|
||||
fun KtExpression.computeTypeInContext(
|
||||
scope: LexicalScope,
|
||||
contextExpression: KtExpression = this,
|
||||
trace: BindingTrace = BindingTraceContext(),
|
||||
dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY,
|
||||
expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE
|
||||
): KotlinType? = computeTypeInfoInContext(scope, contextExpression, trace, dataFlowInfo, expectedType).type
|
||||
|
||||
@JvmOverloads fun KtExpression.analyzeAsReplacement(
|
||||
expressionToBeReplaced: KtExpression,
|
||||
bindingContext: BindingContext,
|
||||
scope: LexicalScope,
|
||||
trace: BindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for analyzeAsReplacement()"),
|
||||
contextDependency: ContextDependency = ContextDependency.INDEPENDENT
|
||||
): BindingContext {
|
||||
return analyzeInContext(scope,
|
||||
expressionToBeReplaced,
|
||||
dataFlowInfo = bindingContext.getDataFlowInfoBefore(expressionToBeReplaced),
|
||||
expectedType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, expressionToBeReplaced] ?: TypeUtils.NO_EXPECTED_TYPE,
|
||||
isStatement = expressionToBeReplaced.isUsedAsStatement(bindingContext),
|
||||
trace = trace,
|
||||
contextDependency = contextDependency)
|
||||
}
|
||||
@JvmOverloads
|
||||
fun KtExpression.analyzeAsReplacement(
|
||||
expressionToBeReplaced: KtExpression,
|
||||
bindingContext: BindingContext,
|
||||
scope: LexicalScope,
|
||||
trace: BindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for analyzeAsReplacement()"),
|
||||
contextDependency: ContextDependency = ContextDependency.INDEPENDENT
|
||||
): BindingContext = analyzeInContext(
|
||||
scope,
|
||||
expressionToBeReplaced,
|
||||
dataFlowInfo = bindingContext.getDataFlowInfoBefore(expressionToBeReplaced),
|
||||
expectedType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, expressionToBeReplaced] ?: TypeUtils.NO_EXPECTED_TYPE,
|
||||
isStatement = expressionToBeReplaced.isUsedAsStatement(bindingContext),
|
||||
trace = trace,
|
||||
contextDependency = contextDependency
|
||||
)
|
||||
|
||||
@JvmOverloads fun KtExpression.analyzeAsReplacement(
|
||||
expressionToBeReplaced: KtExpression,
|
||||
bindingContext: BindingContext,
|
||||
resolutionFacade: ResolutionFacade = expressionToBeReplaced.getResolutionFacade(),
|
||||
trace: BindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for analyzeAsReplacement()"),
|
||||
contextDependency: ContextDependency = ContextDependency.INDEPENDENT
|
||||
@JvmOverloads
|
||||
fun KtExpression.analyzeAsReplacement(
|
||||
expressionToBeReplaced: KtExpression,
|
||||
bindingContext: BindingContext,
|
||||
resolutionFacade: ResolutionFacade = expressionToBeReplaced.getResolutionFacade(),
|
||||
trace: BindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for analyzeAsReplacement()"),
|
||||
contextDependency: ContextDependency = ContextDependency.INDEPENDENT
|
||||
): BindingContext {
|
||||
val scope = expressionToBeReplaced.getResolutionScope(bindingContext, resolutionFacade)
|
||||
return analyzeAsReplacement(expressionToBeReplaced, bindingContext, scope, trace, contextDependency)
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:JvmName("ResolutionUtils")
|
||||
@@ -20,7 +9,8 @@ package org.jetbrains.kotlin.idea.caches.resolve
|
||||
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -165,7 +155,8 @@ inline fun <reified T> T.analyzeWithContent(): BindingContext where T : KtDeclar
|
||||
* @ref [org.jetbrains.kotlin.idea.caches.resolve.PerFileAnalysisCache]
|
||||
*/
|
||||
fun KtFile.analyzeWithAllCompilerChecks(vararg extraFiles: KtFile): AnalysisResult =
|
||||
KotlinCacheService.getInstance(project).getResolutionFacade(listOf(this) + extraFiles.toList()).analyzeWithAllCompilerChecks(listOf(this))
|
||||
KotlinCacheService.getInstance(project).getResolutionFacade(listOf(this) + extraFiles.toList())
|
||||
.analyzeWithAllCompilerChecks(listOf(this))
|
||||
|
||||
/**
|
||||
* This function is expected to produce the same result as compiler for the given element and its children (including diagnostics,
|
||||
@@ -187,13 +178,18 @@ fun KtElement.analyzeWithAllCompilerChecks(): AnalysisResult = getResolutionFaca
|
||||
|
||||
// this method don't check visibility and collect all descriptors with given fqName
|
||||
fun ResolutionFacade.resolveImportReference(
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
fqName: FqName
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
fqName: FqName
|
||||
): Collection<DeclarationDescriptor> {
|
||||
val importDirective = KtPsiFactory(project).createImportDirective(ImportPath(fqName, false))
|
||||
val qualifiedExpressionResolver = this.getFrontendService(moduleDescriptor, QualifiedExpressionResolver::class.java)
|
||||
return qualifiedExpressionResolver.processImportReference(
|
||||
importDirective, moduleDescriptor, BindingTraceContext(), excludedImportNames = emptyList(), packageFragmentForVisibilityCheck = null)?.getContributedDescriptors() ?: emptyList()
|
||||
importDirective,
|
||||
moduleDescriptor,
|
||||
BindingTraceContext(),
|
||||
excludedImportNames = emptyList(),
|
||||
packageFragmentForVisibilityCheck = null
|
||||
)?.getContributedDescriptors() ?: emptyList()
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
|
||||
+9
-18
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.codeInsight
|
||||
@@ -241,9 +230,10 @@ class ReferenceVariantsHelper(
|
||||
|
||||
if (callType == CallType.SUPER_MEMBERS) { // we need to unwrap fake overrides in case of "super." because ShadowedDeclarationsFilter does not work correctly
|
||||
return descriptors.flatMapTo(LinkedHashSet<DeclarationDescriptor>()) {
|
||||
if (it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) it.overriddenDescriptors else listOf(
|
||||
it
|
||||
)
|
||||
if (it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE)
|
||||
it.overriddenDescriptors
|
||||
else
|
||||
listOf(it)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,8 +469,9 @@ fun ResolutionScope.collectSyntheticStaticMembersAndConstructors(
|
||||
nameFilter: (Name) -> Boolean
|
||||
): List<FunctionDescriptor> {
|
||||
val syntheticScopes = resolutionFacade.getFrontendService(SyntheticScopes::class.java)
|
||||
return (syntheticScopes.forceEnableSamAdapters().collectSyntheticStaticFunctions(this) + syntheticScopes.collectSyntheticConstructors(this))
|
||||
.filter { kindFilter.accepts(it) && nameFilter(it.name) }
|
||||
return (syntheticScopes.forceEnableSamAdapters().collectSyntheticStaticFunctions(this) + syntheticScopes.collectSyntheticConstructors(
|
||||
this
|
||||
)).filter { kindFilter.accepts(it) && nameFilter(it.name) }
|
||||
}
|
||||
|
||||
// New Inference disables scope with synthetic SAM-adapters because it uses conversions for resolution
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.kdoc
|
||||
@@ -22,14 +11,24 @@ import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
interface SampleResolutionService {
|
||||
fun resolveSample(context: BindingContext, fromDescriptor: DeclarationDescriptor, resolutionFacade: ResolutionFacade, qualifiedName: List<String>): Collection<DeclarationDescriptor>
|
||||
fun resolveSample(
|
||||
context: BindingContext,
|
||||
fromDescriptor: DeclarationDescriptor,
|
||||
resolutionFacade: ResolutionFacade,
|
||||
qualifiedName: List<String>
|
||||
): Collection<DeclarationDescriptor>
|
||||
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* It's internal implementation, please use [resolveKDocSampleLink], or [resolveKDocLink]
|
||||
*/
|
||||
internal fun resolveSample(context: BindingContext, fromDescriptor: DeclarationDescriptor, resolutionFacade: ResolutionFacade, qualifiedName: List<String>): Collection<DeclarationDescriptor> {
|
||||
internal fun resolveSample(
|
||||
context: BindingContext,
|
||||
fromDescriptor: DeclarationDescriptor,
|
||||
resolutionFacade: ResolutionFacade,
|
||||
qualifiedName: List<String>
|
||||
): Collection<DeclarationDescriptor> {
|
||||
val instance = ServiceManager.getService(resolutionFacade.project, SampleResolutionService::class.java)
|
||||
return instance?.resolveSample(context, fromDescriptor, resolutionFacade, qualifiedName) ?: emptyList()
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.kdoc
|
||||
@@ -46,17 +35,16 @@ import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
fun resolveKDocLink(
|
||||
context: BindingContext,
|
||||
resolutionFacade: ResolutionFacade,
|
||||
fromDescriptor: DeclarationDescriptor,
|
||||
fromSubjectOfTag: KDocTag?,
|
||||
qualifiedName: List<String>
|
||||
): Collection<DeclarationDescriptor> =
|
||||
when (fromSubjectOfTag?.knownTag) {
|
||||
KDocKnownTag.PARAM -> resolveParamLink(fromDescriptor, qualifiedName)
|
||||
KDocKnownTag.SAMPLE -> resolveKDocSampleLink(context, resolutionFacade, fromDescriptor, qualifiedName)
|
||||
else -> resolveDefaultKDocLink(context, resolutionFacade, fromDescriptor, qualifiedName)
|
||||
}
|
||||
context: BindingContext,
|
||||
resolutionFacade: ResolutionFacade,
|
||||
fromDescriptor: DeclarationDescriptor,
|
||||
fromSubjectOfTag: KDocTag?,
|
||||
qualifiedName: List<String>
|
||||
): Collection<DeclarationDescriptor> = when (fromSubjectOfTag?.knownTag) {
|
||||
KDocKnownTag.PARAM -> resolveParamLink(fromDescriptor, qualifiedName)
|
||||
KDocKnownTag.SAMPLE -> resolveKDocSampleLink(context, resolutionFacade, fromDescriptor, qualifiedName)
|
||||
else -> resolveDefaultKDocLink(context, resolutionFacade, fromDescriptor, qualifiedName)
|
||||
}
|
||||
|
||||
|
||||
fun getParamDescriptors(fromDescriptor: DeclarationDescriptor): List<DeclarationDescriptor> {
|
||||
@@ -89,10 +77,10 @@ private fun resolveParamLink(fromDescriptor: DeclarationDescriptor, qualifiedNam
|
||||
}
|
||||
|
||||
fun resolveKDocSampleLink(
|
||||
context: BindingContext,
|
||||
resolutionFacade: ResolutionFacade,
|
||||
fromDescriptor: DeclarationDescriptor,
|
||||
qualifiedName: List<String>
|
||||
context: BindingContext,
|
||||
resolutionFacade: ResolutionFacade,
|
||||
fromDescriptor: DeclarationDescriptor,
|
||||
qualifiedName: List<String>
|
||||
): Collection<DeclarationDescriptor> {
|
||||
|
||||
val resolvedViaService = SampleResolutionService.resolveSample(context, fromDescriptor, resolutionFacade, qualifiedName)
|
||||
@@ -102,10 +90,10 @@ fun resolveKDocSampleLink(
|
||||
}
|
||||
|
||||
private fun resolveDefaultKDocLink(
|
||||
context: BindingContext,
|
||||
resolutionFacade: ResolutionFacade,
|
||||
fromDescriptor: DeclarationDescriptor,
|
||||
qualifiedName: List<String>
|
||||
context: BindingContext,
|
||||
resolutionFacade: ResolutionFacade,
|
||||
fromDescriptor: DeclarationDescriptor,
|
||||
qualifiedName: List<String>
|
||||
): Collection<DeclarationDescriptor> {
|
||||
|
||||
val contextScope = getKDocLinkResolutionScope(resolutionFacade, fromDescriptor)
|
||||
@@ -137,14 +125,19 @@ private fun resolveDefaultKDocLink(
|
||||
val factory = KtPsiFactory(resolutionFacade.project)
|
||||
// TODO escape identifiers
|
||||
val codeFragment = factory.createExpressionCodeFragment(qualifiedName.joinToString("."), contextElement)
|
||||
val qualifiedExpression = codeFragment.findElementAt(codeFragment.textLength - 1)?.getStrictParentOfType<KtQualifiedExpression>() ?: return emptyList()
|
||||
val (descriptor, memberName) = qualifiedExpressionResolver.resolveClassOrPackageInQualifiedExpression(qualifiedExpression, contextScope, context)
|
||||
val qualifiedExpression =
|
||||
codeFragment.findElementAt(codeFragment.textLength - 1)?.getStrictParentOfType<KtQualifiedExpression>() ?: return emptyList()
|
||||
val (descriptor, memberName) = qualifiedExpressionResolver.resolveClassOrPackageInQualifiedExpression(
|
||||
qualifiedExpression,
|
||||
contextScope,
|
||||
context
|
||||
)
|
||||
if (descriptor == null) return emptyList()
|
||||
if (memberName != null) {
|
||||
val memberScope = getKDocLinkMemberScope(descriptor, contextScope)
|
||||
return memberScope.getContributedFunctions(memberName, NoLookupLocation.FROM_IDE) +
|
||||
memberScope.getContributedVariables(memberName, NoLookupLocation.FROM_IDE) +
|
||||
listOfNotNull(memberScope.getContributedClassifier(memberName, NoLookupLocation.FROM_IDE))
|
||||
memberScope.getContributedVariables(memberName, NoLookupLocation.FROM_IDE) +
|
||||
listOfNotNull(memberScope.getContributedClassifier(memberName, NoLookupLocation.FROM_IDE))
|
||||
}
|
||||
return listOf(descriptor)
|
||||
}
|
||||
@@ -155,16 +148,18 @@ private fun getPackageInnerScope(descriptor: PackageFragmentDescriptor): MemberS
|
||||
|
||||
private fun getClassInnerScope(outerScope: LexicalScope, descriptor: ClassDescriptor): LexicalScope {
|
||||
|
||||
val headerScope = LexicalScopeImpl(outerScope, descriptor, false, descriptor.thisAsReceiverParameter,
|
||||
LexicalScopeKind.SYNTHETIC) {
|
||||
val headerScope = LexicalScopeImpl(
|
||||
outerScope, descriptor, false, descriptor.thisAsReceiverParameter,
|
||||
LexicalScopeKind.SYNTHETIC
|
||||
) {
|
||||
descriptor.declaredTypeParameters.forEach { addClassifierDescriptor(it) }
|
||||
descriptor.constructors.forEach { addFunctionDescriptor(it) }
|
||||
}
|
||||
|
||||
val scopeChain = listOfNotNull(
|
||||
descriptor.defaultType.memberScope,
|
||||
descriptor.staticScope,
|
||||
descriptor.companionObjectDescriptor?.defaultType?.memberScope
|
||||
descriptor.defaultType.memberScope,
|
||||
descriptor.staticScope,
|
||||
descriptor.companionObjectDescriptor?.defaultType?.memberScope
|
||||
)
|
||||
return LexicalChainedScope(headerScope, descriptor, false, null, LexicalScopeKind.SYNTHETIC, scopeChain)
|
||||
}
|
||||
@@ -180,9 +175,10 @@ fun getKDocLinkResolutionScope(resolutionFacade: ResolutionFacade, contextDescri
|
||||
is ClassDescriptor ->
|
||||
getClassInnerScope(getOuterScope(contextDescriptor, resolutionFacade), contextDescriptor)
|
||||
|
||||
is FunctionDescriptor ->
|
||||
FunctionDescriptorUtil.getFunctionInnerScope(getOuterScope(contextDescriptor, resolutionFacade),
|
||||
contextDescriptor, LocalRedeclarationChecker.DO_NOTHING)
|
||||
is FunctionDescriptor -> FunctionDescriptorUtil.getFunctionInnerScope(
|
||||
getOuterScope(contextDescriptor, resolutionFacade),
|
||||
contextDescriptor, LocalRedeclarationChecker.DO_NOTHING
|
||||
)
|
||||
|
||||
is PropertyDescriptor ->
|
||||
ScopeUtils.makeScopeForPropertyHeader(getOuterScope(contextDescriptor, resolutionFacade), contextDescriptor)
|
||||
@@ -197,13 +193,14 @@ fun getKDocLinkResolutionScope(resolutionFacade: ResolutionFacade, contextDescri
|
||||
private fun getOuterScope(descriptor: DeclarationDescriptorWithSource, resolutionFacade: ResolutionFacade): LexicalScope {
|
||||
val parent = descriptor.containingDeclaration!!
|
||||
if (parent is PackageFragmentDescriptor) {
|
||||
val containingFile = (descriptor.source as? PsiSourceElement)?.psi?.containingFile as? KtFile
|
||||
?: return LexicalScope.Base(ImportingScope.Empty, parent)
|
||||
val containingFile = (descriptor.source as? PsiSourceElement)?.psi?.containingFile as? KtFile ?: return LexicalScope.Base(
|
||||
ImportingScope.Empty,
|
||||
parent
|
||||
)
|
||||
val kotlinCacheService = ServiceManager.getService(containingFile.project, KotlinCacheService::class.java)
|
||||
val facadeToUse = kotlinCacheService?.getResolutionFacade(listOf(containingFile)) ?: resolutionFacade
|
||||
return facadeToUse.getFileResolutionScope(containingFile)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return getKDocLinkResolutionScope(resolutionFacade, parent)
|
||||
}
|
||||
}
|
||||
@@ -215,12 +212,14 @@ fun getKDocLinkMemberScope(descriptor: DeclarationDescriptor, contextScope: Lexi
|
||||
is PackageViewDescriptor -> descriptor.memberScope
|
||||
|
||||
is ClassDescriptor -> {
|
||||
ChainedMemberScope("Member scope for KDoc resolve", listOfNotNull(
|
||||
ChainedMemberScope(
|
||||
"Member scope for KDoc resolve", listOfNotNull(
|
||||
descriptor.unsubstitutedMemberScope,
|
||||
descriptor.staticScope,
|
||||
descriptor.companionObjectDescriptor?.unsubstitutedMemberScope,
|
||||
ExtensionsScope(descriptor, contextScope)
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
else -> MemberScope.Empty
|
||||
@@ -228,40 +227,53 @@ fun getKDocLinkMemberScope(descriptor: DeclarationDescriptor, contextScope: Lexi
|
||||
}
|
||||
|
||||
private class ExtensionsScope(
|
||||
private val receiverClass: ClassDescriptor,
|
||||
private val contextScope: LexicalScope
|
||||
private val receiverClass: ClassDescriptor,
|
||||
private val contextScope: LexicalScope
|
||||
) : MemberScope {
|
||||
private val receiverTypes = listOf(receiverClass.defaultType)
|
||||
|
||||
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<SimpleFunctionDescriptor> {
|
||||
return contextScope.collectFunctions(name, location)
|
||||
.flatMap { if (it is SimpleFunctionDescriptor && it.isExtension) it.substituteExtensionIfCallable(receiverTypes, CallType.DOT) else emptyList() }
|
||||
return contextScope.collectFunctions(name, location).flatMap {
|
||||
if (it is SimpleFunctionDescriptor && it.isExtension) it.substituteExtensionIfCallable(
|
||||
receiverTypes,
|
||||
CallType.DOT
|
||||
) else emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
|
||||
return contextScope.collectVariables(name, location)
|
||||
.flatMap { if (it is PropertyDescriptor && it.isExtension) it.substituteExtensionIfCallable(receiverTypes, CallType.DOT) else emptyList() }
|
||||
return contextScope.collectVariables(name, location).flatMap {
|
||||
if (it is PropertyDescriptor && it.isExtension) it.substituteExtensionIfCallable(
|
||||
receiverTypes,
|
||||
CallType.DOT
|
||||
) else emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = null
|
||||
|
||||
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
|
||||
override fun getContributedDescriptors(
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean
|
||||
): Collection<DeclarationDescriptor> {
|
||||
if (DescriptorKindExclude.Extensions in kindFilter.excludes) return emptyList()
|
||||
return contextScope.collectDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.NonExtensions, nameFilter, changeNamesForAliased = true)
|
||||
.flatMap { if (it is CallableDescriptor && it.isExtension) it.substituteExtensionIfCallable(receiverTypes, CallType.DOT) else emptyList() }
|
||||
return contextScope.collectDescriptorsFiltered(
|
||||
kindFilter exclude DescriptorKindExclude.NonExtensions,
|
||||
nameFilter,
|
||||
changeNamesForAliased = true
|
||||
).flatMap {
|
||||
if (it is CallableDescriptor && it.isExtension) it.substituteExtensionIfCallable(
|
||||
receiverTypes,
|
||||
CallType.DOT
|
||||
) else emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFunctionNames(): Set<Name> {
|
||||
return getContributedDescriptors(kindFilter = DescriptorKindFilter.FUNCTIONS)
|
||||
.map { it.name }
|
||||
.toSet()
|
||||
}
|
||||
override fun getFunctionNames(): Set<Name> =
|
||||
getContributedDescriptors(kindFilter = DescriptorKindFilter.FUNCTIONS).map { it.name }.toSet()
|
||||
|
||||
override fun getVariableNames(): Set<Name> {
|
||||
return getContributedDescriptors(kindFilter = DescriptorKindFilter.VARIABLES)
|
||||
.map { it.name }
|
||||
.toSet()
|
||||
}
|
||||
override fun getVariableNames(): Set<Name> =
|
||||
getContributedDescriptors(kindFilter = DescriptorKindFilter.VARIABLES).map { it.name }.toSet()
|
||||
|
||||
override fun getClassifierNames() = null
|
||||
|
||||
|
||||
+7
-18
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.introduce
|
||||
@@ -35,11 +24,11 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
class ExtractableSubstringInfo(
|
||||
val startEntry: KtStringTemplateEntry,
|
||||
val endEntry: KtStringTemplateEntry,
|
||||
val prefix: String,
|
||||
val suffix: String,
|
||||
type: KotlinType? = null
|
||||
val startEntry: KtStringTemplateEntry,
|
||||
val endEntry: KtStringTemplateEntry,
|
||||
val prefix: String,
|
||||
val suffix: String,
|
||||
type: KotlinType? = null
|
||||
) {
|
||||
private fun guessLiteralType(literal: String): KotlinType {
|
||||
val facade = template.getResolutionFacade()
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.resolve
|
||||
@@ -51,8 +40,6 @@ interface ResolutionFacade {
|
||||
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> ResolutionFacade.frontendService(): T
|
||||
= this.getFrontendService(T::class.java)
|
||||
inline fun <reified T : Any> ResolutionFacade.frontendService(): T = this.getFrontendService(T::class.java)
|
||||
|
||||
inline fun <reified T : Any> ResolutionFacade.ideService(): T
|
||||
= this.getIdeService(T::class.java)
|
||||
inline fun <reified T : Any> ResolutionFacade.ideService(): T = this.getIdeService(T::class.java)
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
@@ -146,7 +135,8 @@ sealed class CallTypeAndReceiver<TReceiver : KtElement?, out TCallType : CallTyp
|
||||
CallType.IMPORT_DIRECTIVE, receiver
|
||||
)
|
||||
|
||||
class PACKAGE_DIRECTIVE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.PACKAGE_DIRECTIVE>(CallType.PACKAGE_DIRECTIVE, receiver)
|
||||
class PACKAGE_DIRECTIVE(receiver: KtExpression?) :
|
||||
CallTypeAndReceiver<KtExpression?, CallType.PACKAGE_DIRECTIVE>(CallType.PACKAGE_DIRECTIVE, receiver)
|
||||
|
||||
class TYPE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.TYPE>(CallType.TYPE, receiver)
|
||||
class DELEGATE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.DELEGATE>(CallType.DELEGATE, receiver)
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:JvmName("FuzzyTypeUtils")
|
||||
@@ -27,7 +16,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.StrictEqualityTypeChecker
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.util.*
|
||||
|
||||
fun CallableDescriptor.fuzzyReturnType() = returnType?.toFuzzyType(typeParameters)
|
||||
@@ -67,8 +55,8 @@ fun FuzzyType.presentationType(): KotlinType {
|
||||
fun KotlinType.toFuzzyType(freeParameters: Collection<TypeParameterDescriptor>) = FuzzyType(this, freeParameters)
|
||||
|
||||
class FuzzyType(
|
||||
val type: KotlinType,
|
||||
freeParameters: Collection<TypeParameterDescriptor>
|
||||
val type: KotlinType,
|
||||
freeParameters: Collection<TypeParameterDescriptor>
|
||||
) {
|
||||
val freeParameters: Set<TypeParameterDescriptor>
|
||||
|
||||
@@ -79,12 +67,10 @@ class FuzzyType(
|
||||
if (usedTypeParameters.isNotEmpty()) {
|
||||
val originalFreeParameters = freeParameters.map { it.toOriginal() }.toSet()
|
||||
this.freeParameters = usedTypeParameters.filter { it.toOriginal() in originalFreeParameters }.toSet()
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.freeParameters = emptySet()
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.freeParameters = emptySet()
|
||||
}
|
||||
}
|
||||
@@ -115,17 +101,13 @@ class FuzzyType(
|
||||
}
|
||||
}
|
||||
|
||||
fun checkIsSubtypeOf(otherType: FuzzyType): TypeSubstitutor?
|
||||
= matchedSubstitutor(otherType, MatchKind.IS_SUBTYPE)
|
||||
fun checkIsSubtypeOf(otherType: FuzzyType): TypeSubstitutor? = matchedSubstitutor(otherType, MatchKind.IS_SUBTYPE)
|
||||
|
||||
fun checkIsSuperTypeOf(otherType: FuzzyType): TypeSubstitutor?
|
||||
= matchedSubstitutor(otherType, MatchKind.IS_SUPERTYPE)
|
||||
fun checkIsSuperTypeOf(otherType: FuzzyType): TypeSubstitutor? = matchedSubstitutor(otherType, MatchKind.IS_SUPERTYPE)
|
||||
|
||||
fun checkIsSubtypeOf(otherType: KotlinType): TypeSubstitutor?
|
||||
= checkIsSubtypeOf(otherType.toFuzzyType(emptyList()))
|
||||
fun checkIsSubtypeOf(otherType: KotlinType): TypeSubstitutor? = checkIsSubtypeOf(otherType.toFuzzyType(emptyList()))
|
||||
|
||||
fun checkIsSuperTypeOf(otherType: KotlinType): TypeSubstitutor?
|
||||
= checkIsSuperTypeOf(otherType.toFuzzyType(emptyList()))
|
||||
fun checkIsSuperTypeOf(otherType: KotlinType): TypeSubstitutor? = checkIsSuperTypeOf(otherType.toFuzzyType(emptyList()))
|
||||
|
||||
private enum class MatchKind {
|
||||
IS_SUBTYPE,
|
||||
@@ -181,14 +163,14 @@ class FuzzyType(
|
||||
}.buildSubstitutor()
|
||||
|
||||
val substitutionMap: Map<TypeConstructor, TypeProjection> = constraintSystem.typeVariables
|
||||
.map { it.originalTypeParameter }
|
||||
.associateBy(
|
||||
keySelector = { it.typeConstructor },
|
||||
valueTransform = {
|
||||
val typeProjection = TypeProjectionImpl(Variance.INVARIANT, it.defaultType)
|
||||
val substitutedProjection = substitutorToKeepCapturedTypes.substitute(typeProjection)
|
||||
substitutedProjection?.takeUnless { ErrorUtils.containsUninferredParameter(it.type) } ?: typeProjection
|
||||
})
|
||||
.map { it.originalTypeParameter }
|
||||
.associateBy(
|
||||
keySelector = { it.typeConstructor },
|
||||
valueTransform = {
|
||||
val typeProjection = TypeProjectionImpl(Variance.INVARIANT, it.defaultType)
|
||||
val substitutedProjection = substitutorToKeepCapturedTypes.substitute(typeProjection)
|
||||
substitutedProjection?.takeUnless { ErrorUtils.containsUninferredParameter(it.type) } ?: typeProjection
|
||||
})
|
||||
return TypeConstructorSubstitution.createByConstructorsMap(substitutionMap, approximateCapturedTypes = true).buildSubstitutor()
|
||||
}
|
||||
}
|
||||
@@ -199,7 +181,10 @@ fun TypeSubstitution.hasConflictWith(other: TypeSubstitution, freeParameters: Co
|
||||
val type = parameter.defaultType
|
||||
val substituted1 = this[type] ?: return@any false
|
||||
val substituted2 = other[type] ?: return@any false
|
||||
!StrictEqualityTypeChecker.strictEqualTypes(substituted1.type.unwrap(), substituted2.type.unwrap()) || substituted1.projectionKind != substituted2.projectionKind
|
||||
!StrictEqualityTypeChecker.strictEqualTypes(
|
||||
substituted1.type.unwrap(),
|
||||
substituted2.type.unwrap()
|
||||
) || substituted1.projectionKind != substituted2.projectionKind
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
@@ -33,11 +22,16 @@ abstract class ImportInsertHelper {
|
||||
|
||||
abstract val importSortComparator: Comparator<ImportPath>
|
||||
|
||||
abstract fun importDescriptor(file: KtFile, descriptor: DeclarationDescriptor, forceAllUnderImport: Boolean = false): ImportDescriptorResult
|
||||
abstract fun importDescriptor(
|
||||
file: KtFile,
|
||||
descriptor: DeclarationDescriptor,
|
||||
forceAllUnderImport: Boolean = false
|
||||
): ImportDescriptorResult
|
||||
|
||||
companion object {
|
||||
@JvmStatic fun getInstance(project: Project): ImportInsertHelper
|
||||
= ServiceManager.getService<ImportInsertHelper>(project, ImportInsertHelper::class.java)
|
||||
@JvmStatic
|
||||
fun getInstance(project: Project): ImportInsertHelper =
|
||||
ServiceManager.getService<ImportInsertHelper>(project, ImportInsertHelper::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
@@ -29,4 +18,4 @@ fun FunctionDescriptor.shouldNotConvertToProperty(notProperties: Set<FqNameUnsaf
|
||||
}
|
||||
|
||||
fun SyntheticJavaPropertyDescriptor.suppressedByNotPropertyList(set: Set<FqNameUnsafe>) =
|
||||
getMethod.shouldNotConvertToProperty(set) || setMethod?.shouldNotConvertToProperty(set) ?: false
|
||||
getMethod.shouldNotConvertToProperty(set) || setMethod?.shouldNotConvertToProperty(set) ?: false
|
||||
@@ -1,23 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
@@ -40,17 +28,17 @@ import org.jetbrains.kotlin.util.descriptorsEqualWithSubstitution
|
||||
import java.util.*
|
||||
|
||||
class ShadowedDeclarationsFilter(
|
||||
private val bindingContext: BindingContext,
|
||||
private val resolutionFacade: ResolutionFacade,
|
||||
private val context: PsiElement,
|
||||
private val explicitReceiverValue: ReceiverValue?
|
||||
private val bindingContext: BindingContext,
|
||||
private val resolutionFacade: ResolutionFacade,
|
||||
private val context: PsiElement,
|
||||
private val explicitReceiverValue: ReceiverValue?
|
||||
) {
|
||||
companion object {
|
||||
fun create(
|
||||
bindingContext: BindingContext,
|
||||
resolutionFacade: ResolutionFacade,
|
||||
context: PsiElement,
|
||||
callTypeAndReceiver: CallTypeAndReceiver<*, *>
|
||||
bindingContext: BindingContext,
|
||||
resolutionFacade: ResolutionFacade,
|
||||
context: PsiElement,
|
||||
callTypeAndReceiver: CallTypeAndReceiver<*, *>
|
||||
): ShadowedDeclarationsFilter? {
|
||||
val receiverExpression = when (callTypeAndReceiver) {
|
||||
is CallTypeAndReceiver.DEFAULT -> null
|
||||
@@ -73,20 +61,16 @@ class ShadowedDeclarationsFilter(
|
||||
private val psiFactory = KtPsiFactory(resolutionFacade.project)
|
||||
private val dummyExpressionFactory = DummyExpressionFactory(psiFactory)
|
||||
|
||||
fun <TDescriptor : DeclarationDescriptor> filter(declarations: Collection<TDescriptor>): Collection<TDescriptor> {
|
||||
return declarations
|
||||
.groupBy { signature(it) }
|
||||
.values
|
||||
.flatMap { group -> filterEqualSignatureGroup(group) }
|
||||
}
|
||||
fun <TDescriptor : DeclarationDescriptor> filter(declarations: Collection<TDescriptor>): Collection<TDescriptor> =
|
||||
declarations.groupBy { signature(it) }.values.flatMap { group -> filterEqualSignatureGroup(group) }
|
||||
|
||||
fun <TDescriptor : DeclarationDescriptor> createNonImportedDeclarationsFilter(
|
||||
importedDeclarations: Collection<DeclarationDescriptor>
|
||||
importedDeclarations: Collection<DeclarationDescriptor>
|
||||
): (Collection<TDescriptor>) -> Collection<TDescriptor> {
|
||||
val importedDeclarationsSet = importedDeclarations.toSet()
|
||||
val importedDeclarationsBySignature = importedDeclarationsSet.groupBy { signature(it) }
|
||||
|
||||
return filter@ { declarations ->
|
||||
return filter@{ declarations ->
|
||||
// optimization
|
||||
if (declarations.size == 1 && importedDeclarationsBySignature[signature(declarations.single())] == null) return@filter declarations
|
||||
|
||||
@@ -103,19 +87,18 @@ class ShadowedDeclarationsFilter(
|
||||
}
|
||||
}
|
||||
|
||||
private fun signature(descriptor: DeclarationDescriptor): Any =
|
||||
when (descriptor) {
|
||||
is SimpleFunctionDescriptor -> FunctionSignature(descriptor)
|
||||
is VariableDescriptor -> descriptor.name
|
||||
is ClassDescriptor -> descriptor.importableFqName ?: descriptor
|
||||
else -> descriptor
|
||||
}
|
||||
private fun signature(descriptor: DeclarationDescriptor): Any = when (descriptor) {
|
||||
is SimpleFunctionDescriptor -> FunctionSignature(descriptor)
|
||||
is VariableDescriptor -> descriptor.name
|
||||
is ClassDescriptor -> descriptor.importableFqName ?: descriptor
|
||||
else -> descriptor
|
||||
}
|
||||
|
||||
private fun packageName(descriptor: DeclarationDescriptor) = descriptor.importableFqName?.parent()
|
||||
|
||||
private fun <TDescriptor : DeclarationDescriptor> filterEqualSignatureGroup(
|
||||
descriptors: Collection<TDescriptor>,
|
||||
descriptorsToImport: Collection<TDescriptor> = emptyList()
|
||||
descriptors: Collection<TDescriptor>,
|
||||
descriptorsToImport: Collection<TDescriptor> = emptyList()
|
||||
): Collection<TDescriptor> {
|
||||
if (descriptors.size == 1) return descriptors
|
||||
|
||||
@@ -143,7 +126,8 @@ class ShadowedDeclarationsFilter(
|
||||
}
|
||||
|
||||
val firstVarargIndex = parameters.withIndex().firstOrNull { it.value.varargElementType != null }?.index
|
||||
val useNamedFromIndex = if (firstVarargIndex != null && firstVarargIndex != parameters.lastIndex) firstVarargIndex else parameters.size
|
||||
val useNamedFromIndex =
|
||||
if (firstVarargIndex != null && firstVarargIndex != parameters.lastIndex) firstVarargIndex else parameters.size
|
||||
|
||||
class DummyArgument(val index: Int) : ValueArgument {
|
||||
private val expression = dummyArgumentExpressions[index]
|
||||
@@ -153,8 +137,7 @@ class ShadowedDeclarationsFilter(
|
||||
override val asName = parameters[index].name
|
||||
override val referenceExpression = null
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
@@ -206,17 +189,23 @@ class ShadowedDeclarationsFilter(
|
||||
}
|
||||
|
||||
val dataFlowInfo = bindingContext.getDataFlowInfoBefore(context)
|
||||
val context = BasicCallResolutionContext.create(bindingTrace, scope, newCall, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo,
|
||||
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
false, /* languageVersionSettings */ resolutionFacade.frontendService(),
|
||||
resolutionFacade.frontendService<DataFlowValueFactory>())
|
||||
val context = BasicCallResolutionContext.create(
|
||||
bindingTrace, scope, newCall, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo,
|
||||
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
false, /* languageVersionSettings */ resolutionFacade.frontendService(),
|
||||
resolutionFacade.frontendService<DataFlowValueFactory>()
|
||||
)
|
||||
val callResolver = resolutionFacade.frontendService<CallResolver>()
|
||||
val results = if (isFunction) callResolver.resolveFunctionCall(context) else callResolver.resolveSimpleProperty(context)
|
||||
val resultingDescriptors = results.resultingCalls.map { it.resultingDescriptor }
|
||||
val resultingOriginals = resultingDescriptors.mapTo(HashSet<DeclarationDescriptor>()) { it.original }
|
||||
val filtered = descriptors.filter { candidateDescriptor ->
|
||||
candidateDescriptor.original in resultingOriginals /* optimization */
|
||||
&& resultingDescriptors.any { descriptorsEqualWithSubstitution(it, candidateDescriptor) }
|
||||
candidateDescriptor.original in resultingOriginals /* optimization */ && resultingDescriptors.any {
|
||||
descriptorsEqualWithSubstitution(
|
||||
it,
|
||||
candidateDescriptor
|
||||
)
|
||||
}
|
||||
}
|
||||
return if (filtered.isNotEmpty()) filtered else descriptors /* something went wrong, none of our declarations among resolve candidates, let's not filter anything */
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:JvmName("TypeUtils")
|
||||
@@ -69,9 +58,8 @@ private fun KotlinType.approximateNonDynamicFlexibleTypes(
|
||||
|
||||
approximation = if (nullability() == TypeNullability.NOT_NULL) approximation.makeNullableAsSpecified(false) else approximation
|
||||
|
||||
if (approximation.isMarkedNullable && !flexible.lowerBound.isMarkedNullable && TypeUtils.isTypeParameter(approximation) && TypeUtils.hasNullableSuperType(
|
||||
approximation
|
||||
)
|
||||
if (approximation.isMarkedNullable && !flexible.lowerBound
|
||||
.isMarkedNullable && TypeUtils.isTypeParameter(approximation) && TypeUtils.hasNullableSuperType(approximation)
|
||||
) {
|
||||
approximation = approximation.makeNullableAsSpecified(false)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
@@ -56,14 +45,21 @@ fun KtFunctionLiteral.findLabelAndCall(): Pair<Name?, KtCallExpression?> {
|
||||
}
|
||||
|
||||
fun SmartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
|
||||
receiverToCast: ReceiverValue,
|
||||
bindingContext: BindingContext,
|
||||
containingDeclarationOrModule: DeclarationDescriptor,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
dataFlowValueFactory: DataFlowValueFactory
|
||||
receiverToCast: ReceiverValue,
|
||||
bindingContext: BindingContext,
|
||||
containingDeclarationOrModule: DeclarationDescriptor,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
dataFlowValueFactory: DataFlowValueFactory
|
||||
): List<KotlinType> {
|
||||
val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo, languageVersionSettings, dataFlowValueFactory)
|
||||
val variants = getSmartCastVariants(
|
||||
receiverToCast,
|
||||
bindingContext,
|
||||
containingDeclarationOrModule,
|
||||
dataFlowInfo,
|
||||
languageVersionSettings,
|
||||
dataFlowValueFactory
|
||||
)
|
||||
return variants.filter { type ->
|
||||
variants.all { another -> another === type || chooseMoreSpecific(type, another).let { it == null || it === type } }
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:JvmName("ExtensionUtils")
|
||||
@@ -33,8 +22,8 @@ import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.nullability
|
||||
|
||||
fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
||||
receiverTypes: Collection<KotlinType>,
|
||||
callType: CallType<*>
|
||||
receiverTypes: Collection<KotlinType>,
|
||||
callType: CallType<*>
|
||||
): Collection<TCallable> {
|
||||
if (!callType.descriptorKindFilter.accepts(this)) return listOf()
|
||||
|
||||
@@ -44,22 +33,20 @@ fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
||||
}
|
||||
|
||||
val extensionReceiverType = fuzzyExtensionReceiverType()!!
|
||||
val substitutors = types
|
||||
.mapNotNull {
|
||||
var substitutor = extensionReceiverType.checkIsSuperTypeOf(it)
|
||||
// check if we may fail due to receiver expression being nullable
|
||||
if (substitutor == null && it.nullability() == TypeNullability.NULLABLE && extensionReceiverType.nullability() == TypeNullability.NOT_NULL) {
|
||||
substitutor = extensionReceiverType.checkIsSuperTypeOf(it.makeNotNullable())
|
||||
}
|
||||
substitutor
|
||||
}
|
||||
val substitutors = types.mapNotNull {
|
||||
var substitutor = extensionReceiverType.checkIsSuperTypeOf(it)
|
||||
// check if we may fail due to receiver expression being nullable
|
||||
if (substitutor == null && it.nullability() == TypeNullability.NULLABLE && extensionReceiverType.nullability() == TypeNullability.NOT_NULL) {
|
||||
substitutor = extensionReceiverType.checkIsSuperTypeOf(it.makeNotNullable())
|
||||
}
|
||||
substitutor
|
||||
}
|
||||
return if (typeParameters.isEmpty()) { // optimization for non-generic callables
|
||||
if (substitutors.any()) listOf(this) else listOf()
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
substitutors
|
||||
.mapNotNull { @Suppress("UNCHECKED_CAST") (substitute(it) as TCallable?) }
|
||||
.toList()
|
||||
.mapNotNull { @Suppress("UNCHECKED_CAST") (substitute(it) as TCallable?) }
|
||||
.toList()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,20 +63,16 @@ fun ReceiverValue?.getThisReceiverOwner(bindingContext: BindingContext): Declara
|
||||
}
|
||||
}
|
||||
|
||||
fun ReceiverValue?.getReceiverTargetDescriptor(bindingContext: BindingContext): DeclarationDescriptor? {
|
||||
return when (this) {
|
||||
is ExpressionReceiver -> {
|
||||
val expression = KtPsiUtil.deparenthesize(this.expression)
|
||||
val refExpression = when (expression) {
|
||||
is KtThisExpression -> expression.instanceReference
|
||||
is KtReferenceExpression -> expression
|
||||
else -> null
|
||||
} ?: return null
|
||||
bindingContext[BindingContext.REFERENCE_TARGET, refExpression]
|
||||
}
|
||||
|
||||
is ImplicitReceiver -> this.declarationDescriptor
|
||||
|
||||
fun ReceiverValue?.getReceiverTargetDescriptor(bindingContext: BindingContext): DeclarationDescriptor? = when (this) {
|
||||
is ExpressionReceiver -> when (val expression = KtPsiUtil.deparenthesize(this.expression)) {
|
||||
is KtThisExpression -> expression.instanceReference
|
||||
is KtReferenceExpression -> expression
|
||||
else -> null
|
||||
}?.let { referenceExpression ->
|
||||
bindingContext[BindingContext.REFERENCE_TARGET, referenceExpression]
|
||||
}
|
||||
|
||||
is ImplicitReceiver -> this.declarationDescriptor
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
@@ -42,14 +31,10 @@ interface ReceiverExpressionFactory {
|
||||
fun createExpression(psiFactory: KtPsiFactory, shortThis: Boolean = true): KtExpression
|
||||
}
|
||||
|
||||
fun LexicalScope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType: KotlinType): ReceiverExpressionFactory? {
|
||||
return getImplicitReceiversWithInstanceToExpression()
|
||||
.entries
|
||||
.firstOrNull { (receiverDescriptor, _) ->
|
||||
receiverDescriptor.type.isSubtypeOf(receiverType)
|
||||
}
|
||||
?.value
|
||||
}
|
||||
fun LexicalScope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType: KotlinType): ReceiverExpressionFactory? =
|
||||
getImplicitReceiversWithInstanceToExpression().entries.firstOrNull { (receiverDescriptor, _) ->
|
||||
receiverDescriptor.type.isSubtypeOf(receiverType)
|
||||
}?.value
|
||||
|
||||
fun LexicalScope.getImplicitReceiversWithInstanceToExpression(
|
||||
excludeShadowedByDslMarkers: Boolean = false
|
||||
|
||||
+19
-31
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.util.psi.patternMatching
|
||||
@@ -34,7 +23,7 @@ interface KotlinPsiRange {
|
||||
override fun getTextRange(): TextRange = TextRange.EMPTY_RANGE
|
||||
}
|
||||
|
||||
class ListRange(override val elements: List<PsiElement>): KotlinPsiRange {
|
||||
class ListRange(override val elements: List<PsiElement>) : KotlinPsiRange {
|
||||
val startElement: PsiElement = elements.first()
|
||||
val endElement: PsiElement = elements.last()
|
||||
|
||||
@@ -63,29 +52,28 @@ interface KotlinPsiRange {
|
||||
|
||||
val matches = ArrayList<UnificationResult.Matched>()
|
||||
scope.accept(
|
||||
object: KtTreeVisitorVoid() {
|
||||
override fun visitKtElement(element: KtElement) {
|
||||
val range = element
|
||||
.siblings()
|
||||
.filter(SIGNIFICANT_FILTER)
|
||||
.take(elements.size)
|
||||
.toList()
|
||||
.toRange()
|
||||
object : KtTreeVisitorVoid() {
|
||||
override fun visitKtElement(element: KtElement) {
|
||||
val range = element
|
||||
.siblings()
|
||||
.filter(SIGNIFICANT_FILTER)
|
||||
.take(elements.size)
|
||||
.toList()
|
||||
.toRange()
|
||||
|
||||
val result = unifier.unify(range, this@KotlinPsiRange)
|
||||
val result = unifier.unify(range, this@KotlinPsiRange)
|
||||
|
||||
if (result is UnificationResult.StronglyMatched) {
|
||||
if (result is UnificationResult.StronglyMatched) {
|
||||
matches.add(result)
|
||||
} else {
|
||||
val matchCountSoFar = matches.size
|
||||
super.visitKtElement(element)
|
||||
if (result is UnificationResult.WeaklyMatched && matches.size == matchCountSoFar) {
|
||||
matches.add(result)
|
||||
}
|
||||
else {
|
||||
val matchCountSoFar = matches.size
|
||||
super.visitKtElement(element)
|
||||
if (result is UnificationResult.WeaklyMatched && matches.size == matchCountSoFar) {
|
||||
matches.add(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
return matches
|
||||
}
|
||||
|
||||
+141
-140
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.util.psi.patternMatching
|
||||
@@ -71,43 +60,43 @@ interface UnificationResult {
|
||||
override val status: Status get() = UNMATCHED
|
||||
}
|
||||
|
||||
interface Matched: UnificationResult {
|
||||
interface Matched : UnificationResult {
|
||||
val range: KotlinPsiRange
|
||||
val substitution: Map<UnifierParameter, KtElement>
|
||||
override val status: Status get() = MATCHED
|
||||
}
|
||||
|
||||
class StronglyMatched(
|
||||
override val range: KotlinPsiRange,
|
||||
override val substitution: Map<UnifierParameter, KtElement>
|
||||
): Matched
|
||||
override val range: KotlinPsiRange,
|
||||
override val substitution: Map<UnifierParameter, KtElement>
|
||||
) : Matched
|
||||
|
||||
class WeaklyMatched(
|
||||
override val range: KotlinPsiRange,
|
||||
override val substitution: Map<UnifierParameter, KtElement>,
|
||||
val weakMatches: Map<KtElement, KtElement>
|
||||
): Matched
|
||||
override val range: KotlinPsiRange,
|
||||
override val substitution: Map<UnifierParameter, KtElement>,
|
||||
val weakMatches: Map<KtElement, KtElement>
|
||||
) : Matched
|
||||
|
||||
val status: Status
|
||||
val matched: Boolean get() = status != UNMATCHED
|
||||
}
|
||||
|
||||
class UnifierParameter(
|
||||
val descriptor: DeclarationDescriptor,
|
||||
val expectedType: KotlinType?
|
||||
val descriptor: DeclarationDescriptor,
|
||||
val expectedType: KotlinType?
|
||||
)
|
||||
|
||||
class KotlinPsiUnifier(
|
||||
parameters: Collection<UnifierParameter> = Collections.emptySet(),
|
||||
val allowWeakMatches: Boolean = false
|
||||
parameters: Collection<UnifierParameter> = Collections.emptySet(),
|
||||
val allowWeakMatches: Boolean = false
|
||||
) {
|
||||
companion object {
|
||||
val DEFAULT = KotlinPsiUnifier()
|
||||
}
|
||||
|
||||
private inner class Context(
|
||||
val originalTarget: KotlinPsiRange,
|
||||
val originalPattern: KotlinPsiRange
|
||||
val originalTarget: KotlinPsiRange,
|
||||
val originalPattern: KotlinPsiRange
|
||||
) {
|
||||
val patternContext: BindingContext = originalPattern.getBindingContext()
|
||||
val targetContext: BindingContext = originalTarget.getBindingContext()
|
||||
@@ -155,7 +144,7 @@ class KotlinPsiUnifier(
|
||||
|
||||
private fun matchCalls(call1: Call, call2: Call): Boolean {
|
||||
return matchReceivers(call1.explicitReceiver, call2.explicitReceiver) &&
|
||||
matchReceivers(call1.dispatchReceiver, call2.dispatchReceiver)
|
||||
matchReceivers(call1.dispatchReceiver, call2.dispatchReceiver)
|
||||
}
|
||||
|
||||
private fun matchArguments(arg1: ValueArgument, arg2: ValueArgument): Status {
|
||||
@@ -210,25 +199,23 @@ class KotlinPsiUnifier(
|
||||
|
||||
fun checkImplicitReceiver(implicitCall: ResolvedCall<*>, explicitCall: ResolvedCall<*>): Boolean {
|
||||
val (implicitReceiver, explicitReceiver) =
|
||||
when (explicitCall.explicitReceiverKind) {
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER ->
|
||||
(implicitCall.extensionReceiver as? ImplicitReceiver) to
|
||||
(explicitCall.extensionReceiver as? ExpressionReceiver)
|
||||
when (explicitCall.explicitReceiverKind) {
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER ->
|
||||
(implicitCall.extensionReceiver as? ImplicitReceiver) to (explicitCall.extensionReceiver as? ExpressionReceiver)
|
||||
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER ->
|
||||
(implicitCall.dispatchReceiver as? ImplicitReceiver) to
|
||||
(explicitCall.dispatchReceiver as? ExpressionReceiver)
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER ->
|
||||
(implicitCall.dispatchReceiver as? ImplicitReceiver) to (explicitCall.dispatchReceiver as? ExpressionReceiver)
|
||||
|
||||
else ->
|
||||
null to null
|
||||
}
|
||||
else ->
|
||||
null to null
|
||||
}
|
||||
|
||||
val thisExpression = explicitReceiver?.expression as? KtThisExpression
|
||||
if (implicitReceiver == null || thisExpression == null) return false
|
||||
|
||||
return matchDescriptors(
|
||||
implicitReceiver.declarationDescriptor,
|
||||
thisExpression.getAdjustedResolvedCall()?.candidateDescriptor?.containingDeclaration
|
||||
implicitReceiver.declarationDescriptor,
|
||||
thisExpression.getAdjustedResolvedCall()?.candidateDescriptor?.containingDeclaration
|
||||
)
|
||||
}
|
||||
|
||||
@@ -236,7 +223,10 @@ class KotlinPsiUnifier(
|
||||
return when {
|
||||
rc1.explicitReceiverKind == rc2.explicitReceiverKind -> {
|
||||
matchReceivers(rc1.extensionReceiver, rc2.extensionReceiver) &&
|
||||
(rc1.explicitReceiverKind == ExplicitReceiverKind.BOTH_RECEIVERS || matchReceivers(rc1.dispatchReceiver, rc2.dispatchReceiver))
|
||||
(rc1.explicitReceiverKind == ExplicitReceiverKind.BOTH_RECEIVERS || matchReceivers(
|
||||
rc1.dispatchReceiver,
|
||||
rc2.dispatchReceiver
|
||||
))
|
||||
}
|
||||
|
||||
rc1.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER -> checkImplicitReceiver(rc1, rc2)
|
||||
@@ -279,8 +269,7 @@ class KotlinPsiUnifier(
|
||||
private fun KtElement.getAdjustedResolvedCall(): ResolvedCall<*>? {
|
||||
val rc = if (this is KtArrayAccessExpression) {
|
||||
bindingContext[BindingContext.INDEXED_LVALUE_GET, this]
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
getResolvedCall(bindingContext)?.let {
|
||||
when {
|
||||
it !is VariableAsFunctionResolvedCall -> it
|
||||
@@ -330,15 +319,20 @@ class KotlinPsiUnifier(
|
||||
}
|
||||
|
||||
private fun matchTypes(
|
||||
type1: KotlinType?,
|
||||
type2: KotlinType?,
|
||||
typeRef1: KtTypeReference? = null,
|
||||
typeRef2: KtTypeReference? = null
|
||||
type1: KotlinType?,
|
||||
type2: KotlinType?,
|
||||
typeRef1: KtTypeReference? = null,
|
||||
typeRef2: KtTypeReference? = null
|
||||
): Status? {
|
||||
if (type1 != null && type2 != null) {
|
||||
val unwrappedType1 = type1.unwrap()
|
||||
val unwrappedType2 = type2.unwrap()
|
||||
if (unwrappedType1 !== type1 || unwrappedType2 !== type2) return matchTypes(unwrappedType1, unwrappedType2, typeRef1, typeRef2)
|
||||
if (unwrappedType1 !== type1 || unwrappedType2 !== type2) return matchTypes(
|
||||
unwrappedType1,
|
||||
unwrappedType2,
|
||||
typeRef1,
|
||||
typeRef2
|
||||
)
|
||||
|
||||
if (type1.isError || type2.isError) return null
|
||||
if (type1 is AbbreviatedType != type2 is AbbreviatedType) return UNMATCHED
|
||||
@@ -348,16 +342,18 @@ class KotlinPsiUnifier(
|
||||
if (type1.isMarkedNullable != type2.isMarkedNullable) return UNMATCHED
|
||||
if (!matchDescriptors(
|
||||
type1.constructor.declarationDescriptor,
|
||||
type2.constructor.declarationDescriptor)) return UNMATCHED
|
||||
type2.constructor.declarationDescriptor
|
||||
)
|
||||
) return UNMATCHED
|
||||
|
||||
val args1 = type1.arguments
|
||||
val args2 = type2.arguments
|
||||
if (args1.size != args2.size) return UNMATCHED
|
||||
if (!args1.withIndex().all { p ->
|
||||
val (i, arg1) = p
|
||||
val arg2 = args2[i]
|
||||
matchTypeArguments(i, arg1, arg2, typeRef1, typeRef2)
|
||||
}) return UNMATCHED
|
||||
val (i, arg1) = p
|
||||
val arg2 = args2[i]
|
||||
matchTypeArguments(i, arg1, arg2, typeRef1, typeRef2)
|
||||
}) return UNMATCHED
|
||||
|
||||
return MATCHED
|
||||
}
|
||||
@@ -366,11 +362,11 @@ class KotlinPsiUnifier(
|
||||
}
|
||||
|
||||
private fun matchTypeArguments(
|
||||
argIndex: Int,
|
||||
arg1: TypeProjection,
|
||||
arg2: TypeProjection,
|
||||
typeRef1: KtTypeReference?,
|
||||
typeRef2: KtTypeReference?
|
||||
argIndex: Int,
|
||||
arg1: TypeProjection,
|
||||
arg2: TypeProjection,
|
||||
typeRef1: KtTypeReference?,
|
||||
typeRef2: KtTypeReference?
|
||||
): Boolean {
|
||||
val typeArgRef1 = typeRef1?.typeElement?.typeArgumentsAsTypes?.getOrNull(argIndex)
|
||||
val typeArgRef2 = typeRef2?.typeElement?.typeArgumentsAsTypes?.getOrNull(argIndex)
|
||||
@@ -382,11 +378,10 @@ class KotlinPsiUnifier(
|
||||
val status = if (!checkEquivalence && typeRef1 != null && typeRef2 != null) {
|
||||
val typePsi1 = argType1.constructor.declarationDescriptor?.source?.getPsi()
|
||||
val typePsi2 = argType2.constructor.declarationDescriptor?.source?.getPsi()
|
||||
descriptorToParameter[typePsi1]?.let { substitute(it, typeArgRef2) } ?:
|
||||
descriptorToParameter[typePsi2]?.let { substitute(it, typeArgRef1) } ?:
|
||||
matchTypes(argType1, argType2, typeArgRef1, typeArgRef2)
|
||||
}
|
||||
else matchTypes(argType1, argType2, typeArgRef1, typeArgRef2)
|
||||
descriptorToParameter[typePsi1]?.let { substitute(it, typeArgRef2) }
|
||||
?: descriptorToParameter[typePsi2]?.let { substitute(it, typeArgRef1) }
|
||||
?: matchTypes(argType1, argType2, typeArgRef1, typeArgRef2)
|
||||
} else matchTypes(argType1, argType2, typeArgRef1, typeArgRef2)
|
||||
|
||||
return status == MATCHED
|
||||
}
|
||||
@@ -413,12 +408,11 @@ class KotlinPsiUnifier(
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun KtBinaryExpression.matchComplexAssignmentWithSimple(simple: KtBinaryExpression): Status? {
|
||||
return when {
|
||||
doUnify(left, simple.left) == UNMATCHED -> UNMATCHED
|
||||
private fun KtBinaryExpression.matchComplexAssignmentWithSimple(simple: KtBinaryExpression): Status? =
|
||||
when (doUnify(left, simple.left)) {
|
||||
UNMATCHED -> UNMATCHED
|
||||
else -> simple.right?.let { matchCalls(this, it) } ?: UNMATCHED
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtBinaryExpression.matchAssignment(e: KtElement): Status? {
|
||||
val operationType = operationReference.getReferencedNameElementType() as KtToken
|
||||
@@ -435,11 +429,13 @@ class KotlinPsiUnifier(
|
||||
val setResolvedCall = bindingContext[BindingContext.INDEXED_LVALUE_SET, lhs]
|
||||
val resolvedCallToMatch = e.getAdjustedResolvedCall()
|
||||
|
||||
return if (setResolvedCall == null || resolvedCallToMatch == null) null else matchResolvedCalls(setResolvedCall, resolvedCallToMatch)
|
||||
return if (setResolvedCall == null || resolvedCallToMatch == null) null else matchResolvedCalls(
|
||||
setResolvedCall,
|
||||
resolvedCallToMatch
|
||||
)
|
||||
}
|
||||
|
||||
val assignResolvedCall = getAdjustedResolvedCall()
|
||||
if (assignResolvedCall == null) return UNMATCHED
|
||||
val assignResolvedCall = getAdjustedResolvedCall() ?: return UNMATCHED
|
||||
|
||||
val operationName = OperatorConventions.getNameForOperationSymbol(operationType)
|
||||
if (assignResolvedCall.resultingDescriptor?.name == operationName) return matchCalls(this, e)
|
||||
@@ -456,13 +452,11 @@ class KotlinPsiUnifier(
|
||||
|
||||
private fun PsiElement.isIncrement(): Boolean {
|
||||
val parent = parent
|
||||
return parent is KtUnaryExpression
|
||||
&& this == parent.operationReference
|
||||
&& ((parent.operationToken as KtToken) in OperatorConventions.INCREMENT_OPERATIONS)
|
||||
return parent is KtUnaryExpression && this == parent.operationReference && ((parent.operationToken as KtToken) in OperatorConventions.INCREMENT_OPERATIONS)
|
||||
}
|
||||
|
||||
private fun KtCallableReferenceExpression.hasExpressionReceiver(): Boolean =
|
||||
bindingContext[BindingContext.DOUBLE_COLON_LHS, receiverExpression] is DoubleColonLHS.Expression
|
||||
bindingContext[BindingContext.DOUBLE_COLON_LHS, receiverExpression] is DoubleColonLHS.Expression
|
||||
|
||||
private fun matchCallableReferences(e1: KtCallableReferenceExpression, e2: KtCallableReferenceExpression): Status? {
|
||||
if (e1.hasExpressionReceiver() || e2.hasExpressionReceiver()) return null
|
||||
@@ -510,10 +504,11 @@ class KotlinPsiUnifier(
|
||||
}
|
||||
|
||||
private fun matchCallables(
|
||||
decl1: KtDeclaration,
|
||||
decl2: KtDeclaration,
|
||||
desc1: CallableDescriptor,
|
||||
desc2: CallableDescriptor): Status? {
|
||||
decl1: KtDeclaration,
|
||||
decl2: KtDeclaration,
|
||||
desc1: CallableDescriptor,
|
||||
desc2: CallableDescriptor
|
||||
): Status? {
|
||||
fun needToCompareReturnTypes(): Boolean {
|
||||
if (decl1 !is KtCallableDeclaration) return true
|
||||
return decl1.typeReference != null || (decl2 as KtCallableDeclaration).typeReference != null
|
||||
@@ -527,8 +522,11 @@ class KotlinPsiUnifier(
|
||||
val type1 = desc1.returnType
|
||||
val type2 = desc2.returnType
|
||||
|
||||
if (type1 != type2
|
||||
&& (type1 == null || type2 == null || type1.isError || type2.isError || matchTypes(type1, type2) != MATCHED)) {
|
||||
if (type1 != type2 && (type1 == null || type2 == null || type1.isError || type2.isError || matchTypes(
|
||||
type1,
|
||||
type2
|
||||
) != MATCHED)
|
||||
) {
|
||||
return UNMATCHED
|
||||
}
|
||||
}
|
||||
@@ -540,14 +538,14 @@ class KotlinPsiUnifier(
|
||||
val params2 = desc2.valueParameters
|
||||
val zippedParams = params1.zip(params2)
|
||||
val parametersMatch =
|
||||
(params1.size == params2.size) && zippedParams.all { matchTypes(it.first.type, it.second.type) == MATCHED }
|
||||
(params1.size == params2.size) && zippedParams.all { matchTypes(it.first.type, it.second.type) == MATCHED }
|
||||
if (!parametersMatch) return UNMATCHED
|
||||
|
||||
zippedParams.forEach { declarationPatternsToTargets.putValue(it.first, it.second) }
|
||||
|
||||
return doUnify(
|
||||
(decl1 as? KtTypeParameterListOwner)?.typeParameters?.toRange() ?: Empty,
|
||||
(decl2 as? KtTypeParameterListOwner)?.typeParameters?.toRange() ?: Empty
|
||||
(decl1 as? KtTypeParameterListOwner)?.typeParameters?.toRange() ?: Empty,
|
||||
(decl2 as? KtTypeParameterListOwner)?.typeParameters?.toRange() ?: Empty
|
||||
) and when (decl1) {
|
||||
is KtDeclarationWithBody ->
|
||||
doUnify(decl1.bodyExpression, (decl2 as KtDeclarationWithBody).bodyExpression)
|
||||
@@ -570,14 +568,19 @@ class KotlinPsiUnifier(
|
||||
return parent is KtClassBody || parent is KtFile
|
||||
}
|
||||
|
||||
private fun matchNames(decl1: KtDeclaration, decl2: KtDeclaration, desc1: DeclarationDescriptor, desc2: DeclarationDescriptor): Boolean {
|
||||
private fun matchNames(
|
||||
decl1: KtDeclaration,
|
||||
decl2: KtDeclaration,
|
||||
desc1: DeclarationDescriptor,
|
||||
desc2: DeclarationDescriptor
|
||||
): Boolean {
|
||||
return (!decl1.isNameRelevant() && !decl2.isNameRelevant()) || desc1.name == desc2.name
|
||||
}
|
||||
|
||||
private fun <T: DeclarationDescriptor> matchContainedDescriptors(
|
||||
declarations1: List<T>,
|
||||
declarations2: List<T>,
|
||||
matchPair: (Pair<T, T>) -> Boolean
|
||||
private fun <T : DeclarationDescriptor> matchContainedDescriptors(
|
||||
declarations1: List<T>,
|
||||
declarations2: List<T>,
|
||||
matchPair: (Pair<T, T>) -> Boolean
|
||||
): Boolean {
|
||||
val zippedParams = declarations1.zip(declarations2)
|
||||
if (declarations1.size != declarations2.size || !zippedParams.all { matchPair(it) }) return false
|
||||
@@ -587,13 +590,14 @@ class KotlinPsiUnifier(
|
||||
}
|
||||
|
||||
private fun matchClasses(
|
||||
decl1: KtClassOrObject,
|
||||
decl2: KtClassOrObject,
|
||||
desc1: ClassDescriptor,
|
||||
desc2: ClassDescriptor): Status? {
|
||||
decl1: KtClassOrObject,
|
||||
decl2: KtClassOrObject,
|
||||
desc1: ClassDescriptor,
|
||||
desc2: ClassDescriptor
|
||||
): Status? {
|
||||
class OrderInfo<out T>(
|
||||
val orderSensitive: List<T>,
|
||||
val orderInsensitive: List<T>
|
||||
val orderSensitive: List<T>,
|
||||
val orderInsensitive: List<T>
|
||||
)
|
||||
|
||||
fun getMemberOrderInfo(cls: KtClassOrObject): OrderInfo<KtDeclaration> {
|
||||
@@ -610,9 +614,8 @@ class KotlinPsiUnifier(
|
||||
}
|
||||
|
||||
fun resolveAndSortDeclarationsByDescriptor(declarations: List<KtDeclaration>): List<Pair<KtDeclaration, DeclarationDescriptor?>> {
|
||||
return declarations
|
||||
.map { it to it.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it] }
|
||||
.sortedBy { it.second?.let { IdeDescriptorRenderers.SOURCE_CODE.render(it) } ?: "" }
|
||||
return declarations.map { it to it.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it] }
|
||||
.sortedBy { it.second?.let { descriptor -> IdeDescriptorRenderers.SOURCE_CODE.render(descriptor) } ?: "" }
|
||||
}
|
||||
|
||||
fun sortDeclarationsByElementType(declarations: List<KtDeclaration>): List<KtDeclaration> {
|
||||
@@ -642,7 +645,10 @@ class KotlinPsiUnifier(
|
||||
return UNMATCHED
|
||||
}
|
||||
|
||||
val status = doUnify((decl1 as? KtClass)?.getPrimaryConstructorParameterList(), (decl2 as? KtClass)?.getPrimaryConstructorParameterList()) and
|
||||
val status = doUnify(
|
||||
(decl1 as? KtClass)?.getPrimaryConstructorParameterList(),
|
||||
(decl2 as? KtClass)?.getPrimaryConstructorParameterList()
|
||||
) and
|
||||
doUnify((decl1 as? KtClass)?.typeParameterList, (decl2 as? KtClass)?.typeParameterList) and
|
||||
doUnify(delegationInfo1.orderSensitive.toRange(), delegationInfo2.orderSensitive.toRange())
|
||||
if (status == UNMATCHED) return UNMATCHED
|
||||
@@ -654,19 +660,20 @@ class KotlinPsiUnifier(
|
||||
val sortedMembers2 = resolveAndSortDeclarationsByDescriptor(membersInfo2.orderInsensitive)
|
||||
if ((sortedMembers1.size != sortedMembers2.size)) return UNMATCHED
|
||||
if (sortedMembers1.zip(sortedMembers2).any {
|
||||
val (d1, d2) = it
|
||||
(matchDeclarations(d1.first, d2.first, d1.second, d2.second) ?: doUnify(d1.first, d2.first)) == UNMATCHED
|
||||
}) return UNMATCHED
|
||||
val (d1, d2) = it
|
||||
(matchDeclarations(d1.first, d2.first, d1.second, d2.second) ?: doUnify(d1.first, d2.first)) == UNMATCHED
|
||||
}
|
||||
) return UNMATCHED
|
||||
|
||||
return doUnify(
|
||||
sortDeclarationsByElementType(membersInfo1.orderSensitive).toRange(),
|
||||
sortDeclarationsByElementType(membersInfo2.orderSensitive).toRange()
|
||||
sortDeclarationsByElementType(membersInfo1.orderSensitive).toRange(),
|
||||
sortDeclarationsByElementType(membersInfo2.orderSensitive).toRange()
|
||||
)
|
||||
}
|
||||
|
||||
private fun matchTypeParameters(
|
||||
desc1: TypeParameterDescriptor,
|
||||
desc2: TypeParameterDescriptor
|
||||
desc1: TypeParameterDescriptor,
|
||||
desc2: TypeParameterDescriptor
|
||||
): Status {
|
||||
if (desc1.variance != desc2.variance) return UNMATCHED
|
||||
if (!matchTypes(desc1.upperBounds, desc2.upperBounds)) return UNMATCHED
|
||||
@@ -682,18 +689,22 @@ class KotlinPsiUnifier(
|
||||
}
|
||||
|
||||
private fun matchDeclarations(
|
||||
decl1: KtDeclaration,
|
||||
decl2: KtDeclaration,
|
||||
desc1: DeclarationDescriptor?,
|
||||
desc2: DeclarationDescriptor?): Status? {
|
||||
decl1: KtDeclaration,
|
||||
decl2: KtDeclaration,
|
||||
desc1: DeclarationDescriptor?,
|
||||
desc2: DeclarationDescriptor?
|
||||
): Status? {
|
||||
if (decl1::class.java != decl2::class.java) return UNMATCHED
|
||||
|
||||
if (desc1 == null || desc2 == null) {
|
||||
if (decl1 is KtParameter
|
||||
return if (decl1 is KtParameter
|
||||
&& decl2 is KtParameter
|
||||
&& decl1.getStrictParentOfType<KtTypeElement>() != null
|
||||
&& decl2.getStrictParentOfType<KtTypeElement>() != null) return null
|
||||
return UNMATCHED
|
||||
&& decl2.getStrictParentOfType<KtTypeElement>() != null
|
||||
)
|
||||
null
|
||||
else
|
||||
UNMATCHED
|
||||
}
|
||||
if (ErrorUtils.isError(desc1) || ErrorUtils.isError(desc2)) return UNMATCHED
|
||||
if (desc1::class.java != desc2::class.java) return UNMATCHED
|
||||
@@ -801,8 +812,7 @@ class KotlinPsiUnifier(
|
||||
val patternText = pattern.startEntry.text.substring(prefixLength)
|
||||
if (!targetEntryText.endsWith(patternText)) continue
|
||||
targetEntryText.substring(0, targetEntryText.length - patternText.length)
|
||||
}
|
||||
else ""
|
||||
} else ""
|
||||
|
||||
val lastTargetEntry = targetEntries[index + patternEntries.lastIndex]
|
||||
|
||||
@@ -813,8 +823,7 @@ class KotlinPsiUnifier(
|
||||
val lastTargetEntryText = lastTargetEntry.text
|
||||
if (!lastTargetEntryText.startsWith(patternText)) continue
|
||||
lastTargetEntryText.substring(patternText.length)
|
||||
}
|
||||
else ""
|
||||
} else ""
|
||||
|
||||
val fromIndex = if (matchStartByText) 1 else 0
|
||||
val toIndex = if (matchEndByText) patternEntries.lastIndex - 1 else patternEntries.lastIndex
|
||||
@@ -846,8 +855,7 @@ class KotlinPsiUnifier(
|
||||
}
|
||||
}
|
||||
|
||||
private fun ASTNode.getChildrenRange(): KotlinPsiRange =
|
||||
getChildren(null).mapNotNull { it.psi }.toRange()
|
||||
private fun ASTNode.getChildrenRange(): KotlinPsiRange = getChildren(null).mapNotNull { it.psi }.toRange()
|
||||
|
||||
private fun PsiElement.unwrapWeakly(): KtElement? {
|
||||
return when {
|
||||
@@ -860,8 +868,8 @@ class KotlinPsiUnifier(
|
||||
}
|
||||
|
||||
private fun doUnifyWeakly(
|
||||
targetElement: KtElement,
|
||||
patternElement: KtElement
|
||||
targetElement: KtElement,
|
||||
patternElement: KtElement
|
||||
): Status {
|
||||
if (!allowWeakMatches) return UNMATCHED
|
||||
|
||||
@@ -878,10 +886,9 @@ class KotlinPsiUnifier(
|
||||
return status
|
||||
}
|
||||
|
||||
private fun substitute(parameter: UnifierParameter, targetElement: PsiElement?): Status {
|
||||
val existingArgument = substitution[parameter]
|
||||
return when {
|
||||
existingArgument == null -> {
|
||||
private fun substitute(parameter: UnifierParameter, targetElement: PsiElement?): Status =
|
||||
when (val existingArgument = substitution[parameter]) {
|
||||
null -> {
|
||||
substitution[parameter] = targetElement as KtElement
|
||||
MATCHED
|
||||
}
|
||||
@@ -893,11 +900,10 @@ class KotlinPsiUnifier(
|
||||
status
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun doUnify(
|
||||
targetElement: PsiElement?,
|
||||
patternElement: PsiElement?
|
||||
targetElement: PsiElement?,
|
||||
patternElement: PsiElement?
|
||||
): Status {
|
||||
val targetElementUnwrapped = targetElement?.unwrap()
|
||||
val patternElementUnwrapped = patternElement?.unwrap()
|
||||
@@ -922,8 +928,7 @@ class KotlinPsiUnifier(
|
||||
if (referencedPatternDeclaration != null && parameter != null) {
|
||||
if (targetElementUnwrapped is KtExpression) {
|
||||
if (!targetElementUnwrapped.checkType(parameter)) return UNMATCHED
|
||||
}
|
||||
else if (targetElementUnwrapped !is KtUserType) return UNMATCHED
|
||||
} else if (targetElementUnwrapped !is KtUserType) return UNMATCHED
|
||||
|
||||
return substitute(parameter, targetElementUnwrapped)
|
||||
}
|
||||
@@ -958,12 +963,10 @@ class KotlinPsiUnifier(
|
||||
|
||||
private val descriptorToParameter = parameters.associateBy { (it.descriptor as? DeclarationDescriptorWithSource)?.source?.getPsi() }
|
||||
|
||||
private fun PsiElement.unwrap(): PsiElement? {
|
||||
return when (this) {
|
||||
is KtExpression -> KtPsiUtil.deparenthesize(this)
|
||||
is KtStringTemplateEntryWithExpression -> KtPsiUtil.deparenthesize(expression)
|
||||
else -> this
|
||||
}
|
||||
private fun PsiElement.unwrap(): PsiElement? = when (this) {
|
||||
is KtExpression -> KtPsiUtil.deparenthesize(this)
|
||||
is KtStringTemplateEntryWithExpression -> KtPsiUtil.deparenthesize(expression)
|
||||
else -> this
|
||||
}
|
||||
|
||||
private fun PsiElement.unquotedText(): String {
|
||||
@@ -975,8 +978,7 @@ class KotlinPsiUnifier(
|
||||
return with(Context(target, pattern)) {
|
||||
val status = doUnify(target, pattern)
|
||||
when {
|
||||
substitution.size != descriptorToParameter.size ->
|
||||
Unmatched
|
||||
substitution.size != descriptorToParameter.size -> Unmatched
|
||||
status == MATCHED -> {
|
||||
val targetRange = targetSubstringInfo?.createExpression()?.toRange() ?: target
|
||||
if (weakMatches.isEmpty()) {
|
||||
@@ -985,14 +987,13 @@ class KotlinPsiUnifier(
|
||||
WeaklyMatched(targetRange, substitution, weakMatches)
|
||||
}
|
||||
}
|
||||
else ->
|
||||
Unmatched
|
||||
else -> Unmatched
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun unify(targetElement: PsiElement?, patternElement: PsiElement?): UnificationResult =
|
||||
unify(targetElement.toRange(), patternElement.toRange())
|
||||
unify(targetElement.toRange(), patternElement.toRange())
|
||||
}
|
||||
|
||||
fun PsiElement?.matches(e: PsiElement?): Boolean = KotlinPsiUnifier.DEFAULT.unify(this, e).matched
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:JvmName("ScopeUtils")
|
||||
@@ -44,13 +33,15 @@ fun LexicalScope.getAllAccessibleVariables(name: Name): Collection<VariableDescr
|
||||
}
|
||||
|
||||
fun LexicalScope.getAllAccessibleFunctions(name: Name): Collection<FunctionDescriptor> {
|
||||
return getImplicitReceiversWithInstance().flatMap { it.type.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_IDE) } +
|
||||
collectFunctions(name, NoLookupLocation.FROM_IDE)
|
||||
return getImplicitReceiversWithInstance().flatMap {
|
||||
it.type.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_IDE)
|
||||
} + collectFunctions(name, NoLookupLocation.FROM_IDE)
|
||||
}
|
||||
|
||||
fun LexicalScope.getVariablesFromImplicitReceivers(name: Name): Collection<VariableDescriptor> = getImplicitReceiversWithInstance().flatMap {
|
||||
it.type.memberScope.getContributedVariables(name, NoLookupLocation.FROM_IDE)
|
||||
}
|
||||
fun LexicalScope.getVariablesFromImplicitReceivers(name: Name): Collection<VariableDescriptor> =
|
||||
getImplicitReceiversWithInstance().flatMap {
|
||||
it.type.memberScope.getContributedVariables(name, NoLookupLocation.FROM_IDE)
|
||||
}
|
||||
|
||||
fun LexicalScope.getVariableFromImplicitReceivers(name: Name): VariableDescriptor? {
|
||||
getImplicitReceiversWithInstance().forEach {
|
||||
@@ -80,12 +71,12 @@ fun PsiElement.getResolutionScope(bindingContext: BindingContext): LexicalScope?
|
||||
return null
|
||||
}
|
||||
|
||||
fun PsiElement.getResolutionScope(bindingContext: BindingContext, resolutionFacade: ResolutionFacade/*TODO: get rid of this parameter*/): LexicalScope {
|
||||
return getResolutionScope(bindingContext) ?:
|
||||
when (containingFile) {
|
||||
is KtFile -> resolutionFacade.getFileResolutionScope(containingFile as KtFile)
|
||||
else -> error("Not in KtFile")
|
||||
}
|
||||
fun PsiElement.getResolutionScope(
|
||||
bindingContext: BindingContext,
|
||||
resolutionFacade: ResolutionFacade/*TODO: get rid of this parameter*/
|
||||
): LexicalScope = getResolutionScope(bindingContext) ?: when (containingFile) {
|
||||
is KtFile -> resolutionFacade.getFileResolutionScope(containingFile as KtFile)
|
||||
else -> error("Not in KtFile")
|
||||
}
|
||||
|
||||
fun KtElement.getResolutionScope(): LexicalScope {
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.lazy
|
||||
@@ -21,12 +10,16 @@ import org.jetbrains.kotlin.resolve.BindingTraceFilter
|
||||
enum class BodyResolveMode(val bindingTraceFilter: BindingTraceFilter, val doControlFlowAnalysis: Boolean) {
|
||||
// All body statements are analyzed, diagnostics included
|
||||
FULL(BindingTraceFilter.ACCEPT_ALL, doControlFlowAnalysis = true),
|
||||
|
||||
// Analyzes only dependent statements, including all declaration statements (difference from PARTIAL_WITH_CFA)
|
||||
PARTIAL_FOR_COMPLETION(BindingTraceFilter.NO_DIAGNOSTICS, doControlFlowAnalysis = true),
|
||||
|
||||
// Analyzes only dependent statements, diagnostics included
|
||||
PARTIAL_WITH_DIAGNOSTICS(BindingTraceFilter.ACCEPT_ALL, doControlFlowAnalysis = true),
|
||||
|
||||
// Analyzes only dependent statements, performs control flow analysis (mostly needed for isUsedAsExpression / AsStatement)
|
||||
PARTIAL_WITH_CFA(BindingTraceFilter.NO_DIAGNOSTICS, doControlFlowAnalysis = true),
|
||||
|
||||
// Analyzes only dependent statements, including only used declaration statements, does not perform control flow analysis
|
||||
PARTIAL(BindingTraceFilter.NO_DIAGNOSTICS, doControlFlowAnalysis = false)
|
||||
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.lazy
|
||||
@@ -31,9 +20,9 @@ import java.util.*
|
||||
//TODO: do resolve anonymous object's body
|
||||
|
||||
class PartialBodyResolveFilter(
|
||||
elementsToResolve: Collection<KtElement>,
|
||||
private val declaration: KtDeclaration,
|
||||
forCompletion: Boolean
|
||||
elementsToResolve: Collection<KtElement>,
|
||||
private val declaration: KtDeclaration,
|
||||
forCompletion: Boolean
|
||||
) : StatementFilter() {
|
||||
|
||||
private val statementMarks = StatementMarks()
|
||||
@@ -59,8 +48,7 @@ class PartialBodyResolveFilter(
|
||||
if (name != null) {
|
||||
if (declaration is KtNamedFunction) {
|
||||
contextNothingFunctionNames.add(name)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
contextNothingVariableNames.add(name)
|
||||
}
|
||||
}
|
||||
@@ -91,12 +79,11 @@ class PartialBodyResolveFilter(
|
||||
if (name != null && nameFilter(name)) {
|
||||
statementMarks.mark(statement, MarkLevel.NEED_REFERENCE_RESOLVE)
|
||||
}
|
||||
}
|
||||
else if (statement is KtDestructuringDeclaration) {
|
||||
} else if (statement is KtDestructuringDeclaration) {
|
||||
if (statement.entries.any {
|
||||
val name = it.name
|
||||
name != null && nameFilter(name)
|
||||
}) {
|
||||
val name = it.name
|
||||
name != null && nameFilter(name)
|
||||
}) {
|
||||
statementMarks.mark(statement, MarkLevel.NEED_REFERENCE_RESOLVE)
|
||||
}
|
||||
}
|
||||
@@ -116,8 +103,8 @@ class PartialBodyResolveFilter(
|
||||
if (!smartCastPlaces.isEmpty()) {
|
||||
//TODO: do we really need correct resolve for ALL smart cast places?
|
||||
smartCastPlaces.values
|
||||
.flatten()
|
||||
.forEach { statementMarks.mark(it, MarkLevel.NEED_REFERENCE_RESOLVE) }
|
||||
.flatten()
|
||||
.forEach { statementMarks.mark(it, MarkLevel.NEED_REFERENCE_RESOLVE) }
|
||||
updateNameFilter()
|
||||
}
|
||||
}
|
||||
@@ -140,8 +127,8 @@ class PartialBodyResolveFilter(
|
||||
* Returns map from smart-cast expression names (variable name or qualified variable name) to places.
|
||||
*/
|
||||
private fun potentialSmartCastPlaces(
|
||||
statement: KtExpression,
|
||||
filter: (SmartCastName) -> Boolean = { true }
|
||||
statement: KtExpression,
|
||||
filter: (SmartCastName) -> Boolean = { true }
|
||||
): Map<SmartCastName, List<KtExpression>> {
|
||||
val map = HashMap<SmartCastName, ArrayList<KtExpression>>(0)
|
||||
|
||||
@@ -235,9 +222,9 @@ class PartialBodyResolveFilter(
|
||||
|
||||
if (thenBranch != null && elseBranch != null) {
|
||||
val thenCasts = potentialSmartCastPlaces(thenBranch, filter)
|
||||
if (!thenCasts.isEmpty()) {
|
||||
if (thenCasts.isNotEmpty()) {
|
||||
val elseCasts = potentialSmartCastPlaces(elseBranch) { filter(it) && thenCasts.containsKey(it) }
|
||||
if (!elseCasts.isEmpty()) {
|
||||
if (elseCasts.isNotEmpty()) {
|
||||
for ((name, places) in thenCasts) {
|
||||
if (elseCasts.containsKey(name)) { // need filtering by cast names in else-branch
|
||||
addPlaces(name, places)
|
||||
@@ -262,8 +249,7 @@ class PartialBodyResolveFilter(
|
||||
// we need to enter the body only for "while(true)"
|
||||
if (condition.isTrueConstant()) {
|
||||
expression.acceptChildren(this)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
condition?.accept(this)
|
||||
}
|
||||
}
|
||||
@@ -406,8 +392,7 @@ class PartialBodyResolveFilter(
|
||||
insideLoopLevel++
|
||||
loop.body?.accept(this)
|
||||
insideLoopLevel--
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// do not make sense to search exits inside while-loop as not necessary enter it at all
|
||||
condition.accept(this)
|
||||
}
|
||||
@@ -451,8 +436,7 @@ class PartialBodyResolveFilter(
|
||||
if (expression.operationToken == KtTokens.ELVIS) {
|
||||
// do not search exits after "?:"
|
||||
expression.left?.accept(this)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
super.visitBinaryExpression(expression)
|
||||
}
|
||||
}
|
||||
@@ -473,8 +457,8 @@ class PartialBodyResolveFilter(
|
||||
}
|
||||
|
||||
private data class SmartCastName(
|
||||
private val receiverName: SmartCastName?,
|
||||
private val selectorName: String? /* null means "this" (and receiverName should be null */
|
||||
private val receiverName: SmartCastName?,
|
||||
private val selectorName: String? /* null means "this" (and receiverName should be null */
|
||||
) {
|
||||
init {
|
||||
if (selectorName == null) {
|
||||
@@ -482,7 +466,7 @@ class PartialBodyResolveFilter(
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String = if (receiverName != null) receiverName.toString() + "." + selectorName else selectorName ?: "this"
|
||||
override fun toString(): String = if (receiverName != null) "$receiverName.$selectorName" else selectorName ?: "this"
|
||||
|
||||
fun affectsNames(nameFilter: (String) -> Boolean): Boolean {
|
||||
if (selectorName == null) return true
|
||||
@@ -533,8 +517,7 @@ class PartialBodyResolveFilter(
|
||||
if (names == null) return
|
||||
if (filter.names == null) {
|
||||
names = null
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
names!!.addAll(filter.names!!)
|
||||
}
|
||||
}
|
||||
@@ -562,42 +545,38 @@ class PartialBodyResolveFilter(
|
||||
|
||||
private fun KtExpression?.isNullLiteral() = this?.node?.elementType == KtNodeTypes.NULL
|
||||
|
||||
private fun KtExpression?.isTrueConstant()
|
||||
= this != null && node?.elementType == KtNodeTypes.BOOLEAN_CONSTANT && text == "true"
|
||||
private fun KtExpression?.isTrueConstant() = this != null && node?.elementType == KtNodeTypes.BOOLEAN_CONSTANT && text == "true"
|
||||
|
||||
private fun <T : Any> T?.singletonOrEmptySet(): Set<T> = if (this != null) setOf(this) else setOf()
|
||||
|
||||
//TODO: review logic
|
||||
private fun isValueNeeded(expression: KtExpression): Boolean {
|
||||
val parent = expression.parent
|
||||
return when (parent) {
|
||||
is KtBlockExpression -> expression == parent.lastStatement() && isValueNeeded(parent)
|
||||
private fun isValueNeeded(expression: KtExpression): Boolean = when (val parent = expression.parent) {
|
||||
is KtBlockExpression -> expression == parent.lastStatement() && isValueNeeded(parent)
|
||||
|
||||
is KtContainerNode -> { //TODO - not quite correct
|
||||
val pparent = parent.parent as? KtExpression
|
||||
pparent != null && isValueNeeded(pparent)
|
||||
}
|
||||
|
||||
is KtDeclarationWithBody -> {
|
||||
if (expression == parent.bodyExpression)
|
||||
!parent.hasBlockBody() && !parent.hasDeclaredReturnType()
|
||||
else
|
||||
true
|
||||
}
|
||||
|
||||
is KtAnonymousInitializer -> false
|
||||
|
||||
else -> true
|
||||
is KtContainerNode -> { //TODO - not quite correct
|
||||
val pparent = parent.parent as? KtExpression
|
||||
pparent != null && isValueNeeded(pparent)
|
||||
}
|
||||
|
||||
is KtDeclarationWithBody -> {
|
||||
if (expression == parent.bodyExpression)
|
||||
!parent.hasBlockBody() && !parent.hasDeclaredReturnType()
|
||||
else
|
||||
true
|
||||
}
|
||||
|
||||
is KtAnonymousInitializer -> false
|
||||
|
||||
else -> true
|
||||
}
|
||||
|
||||
private fun KtBlockExpression.lastStatement(): KtExpression?
|
||||
= lastChild?.siblings(forward = false)?.firstIsInstanceOrNull<KtExpression>()
|
||||
private fun KtBlockExpression.lastStatement(): KtExpression? =
|
||||
lastChild?.siblings(forward = false)?.firstIsInstanceOrNull<KtExpression>()
|
||||
|
||||
private fun PsiElement.isStatement() = this is KtExpression && parent is KtBlockExpression
|
||||
|
||||
private fun KtTypeReference?.containsProbablyNothing()
|
||||
= this?.typeElement?.anyDescendantOfType<KtUserType> { it.isProbablyNothing() } ?: false
|
||||
private fun KtTypeReference?.containsProbablyNothing() =
|
||||
this?.typeElement?.anyDescendantOfType<KtUserType> { it.isProbablyNothing() } ?: false
|
||||
}
|
||||
|
||||
private inner class StatementMarks {
|
||||
@@ -627,18 +606,16 @@ class PartialBodyResolveFilter(
|
||||
}
|
||||
}
|
||||
|
||||
fun statementMark(statement: KtExpression): MarkLevel
|
||||
= statementMarks[statement] ?: MarkLevel.NONE
|
||||
fun statementMark(statement: KtExpression): MarkLevel = statementMarks[statement] ?: MarkLevel.NONE
|
||||
|
||||
fun allMarkedStatements(): Collection<KtExpression>
|
||||
= statementMarks.keys
|
||||
fun allMarkedStatements(): Collection<KtExpression> = statementMarks.keys
|
||||
|
||||
fun lastMarkedStatement(block: KtBlockExpression, minLevel: MarkLevel): KtExpression? {
|
||||
val level = blockLevels[block] ?: MarkLevel.NONE
|
||||
if (level < minLevel) return null // optimization
|
||||
return block.lastChild.siblings(forward = false)
|
||||
.filterIsInstance<KtExpression>()
|
||||
.first { statementMark(it) >= minLevel }
|
||||
.filterIsInstance<KtExpression>()
|
||||
.first { statementMark(it) >= minLevel }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.scopes
|
||||
@@ -23,20 +12,22 @@ import org.jetbrains.kotlin.utils.Printer
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
|
||||
class ExplicitImportsScope(private val descriptors: Collection<DeclarationDescriptor>) : BaseImportingScope(null) {
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation)
|
||||
= descriptors.filter { it.name == name }.firstIsInstanceOrNull<ClassifierDescriptor>()
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation) =
|
||||
descriptors.filter { it.name == name }.firstIsInstanceOrNull<ClassifierDescriptor>()
|
||||
|
||||
override fun getContributedPackage(name: Name)
|
||||
= descriptors.filter { it.name == name }.firstIsInstanceOrNull<PackageViewDescriptor>()
|
||||
override fun getContributedPackage(name: Name) = descriptors.filter { it.name == name }.firstIsInstanceOrNull<PackageViewDescriptor>()
|
||||
|
||||
override fun getContributedVariables(name: Name, location: LookupLocation)
|
||||
= descriptors.filter { it.name == name }.filterIsInstance<VariableDescriptor>()
|
||||
override fun getContributedVariables(name: Name, location: LookupLocation) =
|
||||
descriptors.filter { it.name == name }.filterIsInstance<VariableDescriptor>()
|
||||
|
||||
override fun getContributedFunctions(name: Name, location: LookupLocation)
|
||||
= descriptors.filter { it.name == name }.filterIsInstance<FunctionDescriptor>()
|
||||
override fun getContributedFunctions(name: Name, location: LookupLocation) =
|
||||
descriptors.filter { it.name == name }.filterIsInstance<FunctionDescriptor>()
|
||||
|
||||
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean, changeNamesForAliased: Boolean)
|
||||
= descriptors
|
||||
override fun getContributedDescriptors(
|
||||
kindFilter: DescriptorKindFilter,
|
||||
nameFilter: (Name) -> Boolean,
|
||||
changeNamesForAliased: Boolean
|
||||
) = descriptors
|
||||
|
||||
override fun computeImportedNames() = descriptors.mapTo(hashSetOf()) { it.name }
|
||||
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.util
|
||||
@@ -31,9 +20,9 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeCheckerImpl
|
||||
import org.jetbrains.kotlin.types.typeUtil.equalTypesOrNulls
|
||||
|
||||
fun descriptorsEqualWithSubstitution(
|
||||
descriptor1: DeclarationDescriptor?,
|
||||
descriptor2: DeclarationDescriptor?,
|
||||
checkOriginals: Boolean = true
|
||||
descriptor1: DeclarationDescriptor?,
|
||||
descriptor2: DeclarationDescriptor?,
|
||||
checkOriginals: Boolean = true
|
||||
): Boolean {
|
||||
if (descriptor1 == descriptor2) return true
|
||||
if (descriptor1 == null || descriptor2 == null) return false
|
||||
@@ -41,14 +30,15 @@ fun descriptorsEqualWithSubstitution(
|
||||
if (descriptor1 !is CallableDescriptor) return true
|
||||
descriptor2 as CallableDescriptor
|
||||
|
||||
val typeChecker = KotlinTypeCheckerImpl.withAxioms(object: KotlinTypeChecker.TypeConstructorEquality {
|
||||
val typeChecker = KotlinTypeCheckerImpl.withAxioms(object : KotlinTypeChecker.TypeConstructorEquality {
|
||||
override fun equals(a: TypeConstructor, b: TypeConstructor): Boolean {
|
||||
val typeParam1 = a.declarationDescriptor as? TypeParameterDescriptor
|
||||
val typeParam2 = b.declarationDescriptor as? TypeParameterDescriptor
|
||||
if (typeParam1 != null
|
||||
&& typeParam2 != null
|
||||
&& typeParam1.containingDeclaration == descriptor1
|
||||
&& typeParam2.containingDeclaration == descriptor2) {
|
||||
&& typeParam2.containingDeclaration == descriptor2
|
||||
) {
|
||||
return typeParam1.index == typeParam2.index
|
||||
}
|
||||
|
||||
@@ -68,25 +58,25 @@ fun descriptorsEqualWithSubstitution(
|
||||
}
|
||||
|
||||
fun ClassDescriptor.findCallableMemberBySignature(
|
||||
signature: CallableMemberDescriptor,
|
||||
allowOverridabilityConflicts: Boolean = false
|
||||
signature: CallableMemberDescriptor,
|
||||
allowOverridabilityConflicts: Boolean = false
|
||||
): CallableMemberDescriptor? {
|
||||
val descriptorKind = if (signature is FunctionDescriptor) DescriptorKindFilter.FUNCTIONS else DescriptorKindFilter.VARIABLES
|
||||
return defaultType.memberScope
|
||||
.getContributedDescriptors(descriptorKind)
|
||||
.filterIsInstance<CallableMemberDescriptor>()
|
||||
.firstOrNull {
|
||||
if (it.containingDeclaration != this) return@firstOrNull false
|
||||
val overridability = OverridingUtil.DEFAULT.isOverridableBy(it as CallableDescriptor, signature, null).result
|
||||
overridability == OVERRIDABLE || (allowOverridabilityConflicts && overridability == CONFLICT)
|
||||
}
|
||||
.getContributedDescriptors(descriptorKind)
|
||||
.filterIsInstance<CallableMemberDescriptor>()
|
||||
.firstOrNull {
|
||||
if (it.containingDeclaration != this) return@firstOrNull false
|
||||
val overridability = OverridingUtil.DEFAULT.isOverridableBy(it as CallableDescriptor, signature, null).result
|
||||
overridability == OVERRIDABLE || (allowOverridabilityConflicts && overridability == CONFLICT)
|
||||
}
|
||||
}
|
||||
|
||||
fun TypeConstructor.supertypesWithAny(): Collection<KotlinType> {
|
||||
val supertypes = supertypes
|
||||
val noSuperClass = supertypes
|
||||
.map { it.constructor.declarationDescriptor as? ClassDescriptor }
|
||||
.all { it == null || it.kind == ClassKind.INTERFACE }
|
||||
val noSuperClass = supertypes.map { it.constructor.declarationDescriptor as? ClassDescriptor }.all {
|
||||
it == null || it.kind == ClassKind.INTERFACE
|
||||
}
|
||||
return if (noSuperClass) supertypes + builtIns.anyType else supertypes
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.types.substitutions
|
||||
@@ -20,7 +9,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
|
||||
import java.util.LinkedHashMap
|
||||
import java.util.*
|
||||
|
||||
fun getTypeSubstitution(baseType: KotlinType, derivedType: KotlinType): LinkedHashMap<TypeConstructor, TypeProjection>? {
|
||||
val substitutedType = TypeCheckingProcedure.findCorrespondingSupertype(derivedType, baseType) ?: return null
|
||||
@@ -34,8 +23,8 @@ fun getTypeSubstitution(baseType: KotlinType, derivedType: KotlinType): LinkedHa
|
||||
}
|
||||
|
||||
fun getCallableSubstitution(
|
||||
baseCallable: CallableDescriptor,
|
||||
derivedCallable: CallableDescriptor
|
||||
baseCallable: CallableDescriptor,
|
||||
derivedCallable: CallableDescriptor
|
||||
): MutableMap<TypeConstructor, TypeProjection>? {
|
||||
val baseClass = baseCallable.containingDeclaration as? ClassDescriptor ?: return null
|
||||
val derivedClass = derivedCallable.containingDeclaration as? ClassDescriptor ?: return null
|
||||
@@ -49,8 +38,8 @@ fun getCallableSubstitution(
|
||||
}
|
||||
|
||||
fun getCallableSubstitutor(
|
||||
baseCallable: CallableDescriptor,
|
||||
derivedCallable: CallableDescriptor
|
||||
baseCallable: CallableDescriptor,
|
||||
derivedCallable: CallableDescriptor
|
||||
): TypeSubstitutor? {
|
||||
return getCallableSubstitution(baseCallable, derivedCallable)?.let { TypeSubstitutor.create(it) }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user