idea: cleanup code

This commit is contained in:
Dmitry Gridin
2019-12-13 22:11:25 +07:00
parent e77d8657f4
commit 8dbbd64beb
897 changed files with 13161 additions and 18514 deletions
+2 -4
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2000-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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -125,7 +125,6 @@ class FirExplorerToolWindow(private val project: Project, private val toolWindow
val psi = (data as? FirElement)?.psi val psi = (data as? FirElement)?.psi
if (data is FirElement && psi != null) { if (data is FirElement && psi != null) {
if (FileDocumentManager.getInstance().getFile(currentEditor.document) == psi.containingFile.virtualFile) { if (FileDocumentManager.getInstance().getFile(currentEditor.document) == psi.containingFile.virtualFile) {
rangeHighlightMarkers += currentEditor.markupModel.addRangeHighlighter( rangeHighlightMarkers += currentEditor.markupModel.addRangeHighlighter(
psi.startOffset, psi.startOffset,
min(currentEditor.document.textLength, psi.endOffset), min(currentEditor.document.textLength, psi.endOffset),
@@ -288,8 +287,7 @@ private fun KType.renderSimple(): String {
} }
return buildString { return buildString {
val classifier = classifier when (val classifier = classifier) {
when (classifier) {
is KClass<*> -> append(classifier.simpleName) is KClass<*> -> append(classifier.simpleName)
is KTypeParameter -> append(classifier.name) is KTypeParameter -> append(classifier.name)
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.analysis 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.KotlinTypeInfo
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor
@JvmOverloads fun KtExpression.computeTypeInfoInContext( @JvmOverloads
scope: LexicalScope, fun KtExpression.computeTypeInfoInContext(
contextExpression: KtExpression = this, scope: LexicalScope,
trace: BindingTrace = BindingTraceContext(), contextExpression: KtExpression = this,
dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY, trace: BindingTrace = BindingTraceContext(),
expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY,
isStatement: Boolean = false, expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE,
contextDependency: ContextDependency = ContextDependency.INDEPENDENT, isStatement: Boolean = false,
expressionTypingServices: ExpressionTypingServices = contextExpression.getResolutionFacade().frontendService<ExpressionTypingServices>() contextDependency: ContextDependency = ContextDependency.INDEPENDENT,
expressionTypingServices: ExpressionTypingServices = contextExpression.getResolutionFacade().frontendService<ExpressionTypingServices>()
): KotlinTypeInfo { ): KotlinTypeInfo {
PreliminaryDeclarationVisitor.createForExpression(this, trace, expressionTypingServices.languageVersionSettings) PreliminaryDeclarationVisitor.createForExpression(this, trace, expressionTypingServices.languageVersionSettings)
return expressionTypingServices.getTypeInfo( return expressionTypingServices.getTypeInfo(
@@ -53,52 +43,63 @@ import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor
) )
} }
@JvmOverloads fun KtExpression.analyzeInContext( @JvmOverloads
scope: LexicalScope, fun KtExpression.analyzeInContext(
contextExpression: KtExpression = this, scope: LexicalScope,
trace: BindingTrace = BindingTraceContext(), contextExpression: KtExpression = this,
dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY, trace: BindingTrace = BindingTraceContext(),
expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY,
isStatement: Boolean = false, expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE,
contextDependency: ContextDependency = ContextDependency.INDEPENDENT, isStatement: Boolean = false,
expressionTypingServices: ExpressionTypingServices = contextExpression.getResolutionFacade().frontendService<ExpressionTypingServices>() contextDependency: ContextDependency = ContextDependency.INDEPENDENT,
expressionTypingServices: ExpressionTypingServices = contextExpression.getResolutionFacade().frontendService<ExpressionTypingServices>()
): BindingContext { ): BindingContext {
computeTypeInfoInContext(scope, contextExpression, trace, dataFlowInfo, expectedType, isStatement, contextDependency, expressionTypingServices) computeTypeInfoInContext(
scope,
contextExpression,
trace,
dataFlowInfo,
expectedType,
isStatement,
contextDependency,
expressionTypingServices
)
return trace.bindingContext return trace.bindingContext
} }
@JvmOverloads fun KtExpression.computeTypeInContext( @JvmOverloads
scope: LexicalScope, fun KtExpression.computeTypeInContext(
contextExpression: KtExpression = this, scope: LexicalScope,
trace: BindingTrace = BindingTraceContext(), contextExpression: KtExpression = this,
dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY, trace: BindingTrace = BindingTraceContext(),
expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE dataFlowInfo: DataFlowInfo = DataFlowInfo.EMPTY,
): KotlinType? { expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE
return computeTypeInfoInContext(scope, contextExpression, trace, dataFlowInfo, expectedType).type ): KotlinType? = computeTypeInfoInContext(scope, contextExpression, trace, dataFlowInfo, expectedType).type
}
@JvmOverloads fun KtExpression.analyzeAsReplacement( @JvmOverloads
expressionToBeReplaced: KtExpression, fun KtExpression.analyzeAsReplacement(
bindingContext: BindingContext, expressionToBeReplaced: KtExpression,
scope: LexicalScope, bindingContext: BindingContext,
trace: BindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for analyzeAsReplacement()"), scope: LexicalScope,
contextDependency: ContextDependency = ContextDependency.INDEPENDENT trace: BindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for analyzeAsReplacement()"),
): BindingContext { contextDependency: ContextDependency = ContextDependency.INDEPENDENT
return analyzeInContext(scope, ): BindingContext = analyzeInContext(
expressionToBeReplaced, scope,
dataFlowInfo = bindingContext.getDataFlowInfoBefore(expressionToBeReplaced), expressionToBeReplaced,
expectedType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, expressionToBeReplaced] ?: TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo = bindingContext.getDataFlowInfoBefore(expressionToBeReplaced),
isStatement = expressionToBeReplaced.isUsedAsStatement(bindingContext), expectedType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, expressionToBeReplaced] ?: TypeUtils.NO_EXPECTED_TYPE,
trace = trace, isStatement = expressionToBeReplaced.isUsedAsStatement(bindingContext),
contextDependency = contextDependency) trace = trace,
} contextDependency = contextDependency
)
@JvmOverloads fun KtExpression.analyzeAsReplacement( @JvmOverloads
expressionToBeReplaced: KtExpression, fun KtExpression.analyzeAsReplacement(
bindingContext: BindingContext, expressionToBeReplaced: KtExpression,
resolutionFacade: ResolutionFacade = expressionToBeReplaced.getResolutionFacade(), bindingContext: BindingContext,
trace: BindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for analyzeAsReplacement()"), resolutionFacade: ResolutionFacade = expressionToBeReplaced.getResolutionFacade(),
contextDependency: ContextDependency = ContextDependency.INDEPENDENT trace: BindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for analyzeAsReplacement()"),
contextDependency: ContextDependency = ContextDependency.INDEPENDENT
): BindingContext { ): BindingContext {
val scope = expressionToBeReplaced.getResolutionScope(bindingContext, resolutionFacade) val scope = expressionToBeReplaced.getResolutionScope(bindingContext, resolutionFacade)
return analyzeAsReplacement(expressionToBeReplaced, bindingContext, scope, trace, contextDependency) return analyzeAsReplacement(expressionToBeReplaced, bindingContext, scope, trace, contextDependency)
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* 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.
*/ */
@file:JvmName("ResolutionUtils") @file:JvmName("ResolutionUtils")
@@ -20,7 +9,8 @@ package org.jetbrains.kotlin.idea.caches.resolve
import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService 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.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.* 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] * @ref [org.jetbrains.kotlin.idea.caches.resolve.PerFileAnalysisCache]
*/ */
fun KtFile.analyzeWithAllCompilerChecks(vararg extraFiles: KtFile): AnalysisResult = 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, * 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 // this method don't check visibility and collect all descriptors with given fqName
fun ResolutionFacade.resolveImportReference( fun ResolutionFacade.resolveImportReference(
moduleDescriptor: ModuleDescriptor, moduleDescriptor: ModuleDescriptor,
fqName: FqName fqName: FqName
): Collection<DeclarationDescriptor> { ): Collection<DeclarationDescriptor> {
val importDirective = KtPsiFactory(project).createImportDirective(ImportPath(fqName, false)) val importDirective = KtPsiFactory(project).createImportDirective(ImportPath(fqName, false))
val qualifiedExpressionResolver = this.getFrontendService(moduleDescriptor, QualifiedExpressionResolver::class.java) val qualifiedExpressionResolver = this.getFrontendService(moduleDescriptor, QualifiedExpressionResolver::class.java)
return qualifiedExpressionResolver.processImportReference( return qualifiedExpressionResolver.processImportReference(
importDirective, moduleDescriptor, BindingTraceContext(), excludedImportNames = emptyList(), packageFragmentForVisibilityCheck = null)?.getContributedDescriptors() ?: emptyList() importDirective,
moduleDescriptor,
BindingTraceContext(),
excludedImportNames = emptyList(),
packageFragmentForVisibilityCheck = null
)?.getContributedDescriptors() ?: emptyList()
} }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.codeInsight 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 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>()) { return descriptors.flatMapTo(LinkedHashSet<DeclarationDescriptor>()) {
if (it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) it.overriddenDescriptors else listOf( if (it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE)
it it.overriddenDescriptors
) else
listOf(it)
} }
} }
@@ -479,8 +469,9 @@ fun ResolutionScope.collectSyntheticStaticMembersAndConstructors(
nameFilter: (Name) -> Boolean nameFilter: (Name) -> Boolean
): List<FunctionDescriptor> { ): List<FunctionDescriptor> {
val syntheticScopes = resolutionFacade.getFrontendService(SyntheticScopes::class.java) val syntheticScopes = resolutionFacade.getFrontendService(SyntheticScopes::class.java)
return (syntheticScopes.forceEnableSamAdapters().collectSyntheticStaticFunctions(this) + syntheticScopes.collectSyntheticConstructors(this)) return (syntheticScopes.forceEnableSamAdapters().collectSyntheticStaticFunctions(this) + syntheticScopes.collectSyntheticConstructors(
.filter { kindFilter.accepts(it) && nameFilter(it.name) } this
)).filter { kindFilter.accepts(it) && nameFilter(it.name) }
} }
// New Inference disables scope with synthetic SAM-adapters because it uses conversions for resolution // 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. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.kdoc package org.jetbrains.kotlin.idea.kdoc
@@ -22,14 +11,24 @@ import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
interface SampleResolutionService { 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 { companion object {
/** /**
* It's internal implementation, please use [resolveKDocSampleLink], or [resolveKDocLink] * 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) val instance = ServiceManager.getService(resolutionFacade.project, SampleResolutionService::class.java)
return instance?.resolveSample(context, fromDescriptor, resolutionFacade, qualifiedName) ?: emptyList() return instance?.resolveSample(context, fromDescriptor, resolutionFacade, qualifiedName) ?: emptyList()
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.kdoc package org.jetbrains.kotlin.idea.kdoc
@@ -46,17 +35,16 @@ import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
fun resolveKDocLink( fun resolveKDocLink(
context: BindingContext, context: BindingContext,
resolutionFacade: ResolutionFacade, resolutionFacade: ResolutionFacade,
fromDescriptor: DeclarationDescriptor, fromDescriptor: DeclarationDescriptor,
fromSubjectOfTag: KDocTag?, fromSubjectOfTag: KDocTag?,
qualifiedName: List<String> qualifiedName: List<String>
): Collection<DeclarationDescriptor> = ): Collection<DeclarationDescriptor> = when (fromSubjectOfTag?.knownTag) {
when (fromSubjectOfTag?.knownTag) { KDocKnownTag.PARAM -> resolveParamLink(fromDescriptor, qualifiedName)
KDocKnownTag.PARAM -> resolveParamLink(fromDescriptor, qualifiedName) KDocKnownTag.SAMPLE -> resolveKDocSampleLink(context, resolutionFacade, fromDescriptor, qualifiedName)
KDocKnownTag.SAMPLE -> resolveKDocSampleLink(context, resolutionFacade, fromDescriptor, qualifiedName) else -> resolveDefaultKDocLink(context, resolutionFacade, fromDescriptor, qualifiedName)
else -> resolveDefaultKDocLink(context, resolutionFacade, fromDescriptor, qualifiedName) }
}
fun getParamDescriptors(fromDescriptor: DeclarationDescriptor): List<DeclarationDescriptor> { fun getParamDescriptors(fromDescriptor: DeclarationDescriptor): List<DeclarationDescriptor> {
@@ -89,10 +77,10 @@ private fun resolveParamLink(fromDescriptor: DeclarationDescriptor, qualifiedNam
} }
fun resolveKDocSampleLink( fun resolveKDocSampleLink(
context: BindingContext, context: BindingContext,
resolutionFacade: ResolutionFacade, resolutionFacade: ResolutionFacade,
fromDescriptor: DeclarationDescriptor, fromDescriptor: DeclarationDescriptor,
qualifiedName: List<String> qualifiedName: List<String>
): Collection<DeclarationDescriptor> { ): Collection<DeclarationDescriptor> {
val resolvedViaService = SampleResolutionService.resolveSample(context, fromDescriptor, resolutionFacade, qualifiedName) val resolvedViaService = SampleResolutionService.resolveSample(context, fromDescriptor, resolutionFacade, qualifiedName)
@@ -102,10 +90,10 @@ fun resolveKDocSampleLink(
} }
private fun resolveDefaultKDocLink( private fun resolveDefaultKDocLink(
context: BindingContext, context: BindingContext,
resolutionFacade: ResolutionFacade, resolutionFacade: ResolutionFacade,
fromDescriptor: DeclarationDescriptor, fromDescriptor: DeclarationDescriptor,
qualifiedName: List<String> qualifiedName: List<String>
): Collection<DeclarationDescriptor> { ): Collection<DeclarationDescriptor> {
val contextScope = getKDocLinkResolutionScope(resolutionFacade, fromDescriptor) val contextScope = getKDocLinkResolutionScope(resolutionFacade, fromDescriptor)
@@ -137,14 +125,19 @@ private fun resolveDefaultKDocLink(
val factory = KtPsiFactory(resolutionFacade.project) val factory = KtPsiFactory(resolutionFacade.project)
// TODO escape identifiers // TODO escape identifiers
val codeFragment = factory.createExpressionCodeFragment(qualifiedName.joinToString("."), contextElement) val codeFragment = factory.createExpressionCodeFragment(qualifiedName.joinToString("."), contextElement)
val qualifiedExpression = codeFragment.findElementAt(codeFragment.textLength - 1)?.getStrictParentOfType<KtQualifiedExpression>() ?: return emptyList() val qualifiedExpression =
val (descriptor, memberName) = qualifiedExpressionResolver.resolveClassOrPackageInQualifiedExpression(qualifiedExpression, contextScope, context) codeFragment.findElementAt(codeFragment.textLength - 1)?.getStrictParentOfType<KtQualifiedExpression>() ?: return emptyList()
val (descriptor, memberName) = qualifiedExpressionResolver.resolveClassOrPackageInQualifiedExpression(
qualifiedExpression,
contextScope,
context
)
if (descriptor == null) return emptyList() if (descriptor == null) return emptyList()
if (memberName != null) { if (memberName != null) {
val memberScope = getKDocLinkMemberScope(descriptor, contextScope) val memberScope = getKDocLinkMemberScope(descriptor, contextScope)
return memberScope.getContributedFunctions(memberName, NoLookupLocation.FROM_IDE) + return memberScope.getContributedFunctions(memberName, NoLookupLocation.FROM_IDE) +
memberScope.getContributedVariables(memberName, NoLookupLocation.FROM_IDE) + memberScope.getContributedVariables(memberName, NoLookupLocation.FROM_IDE) +
listOfNotNull(memberScope.getContributedClassifier(memberName, NoLookupLocation.FROM_IDE)) listOfNotNull(memberScope.getContributedClassifier(memberName, NoLookupLocation.FROM_IDE))
} }
return listOf(descriptor) return listOf(descriptor)
} }
@@ -155,16 +148,18 @@ private fun getPackageInnerScope(descriptor: PackageFragmentDescriptor): MemberS
private fun getClassInnerScope(outerScope: LexicalScope, descriptor: ClassDescriptor): LexicalScope { private fun getClassInnerScope(outerScope: LexicalScope, descriptor: ClassDescriptor): LexicalScope {
val headerScope = LexicalScopeImpl(outerScope, descriptor, false, descriptor.thisAsReceiverParameter, val headerScope = LexicalScopeImpl(
LexicalScopeKind.SYNTHETIC) { outerScope, descriptor, false, descriptor.thisAsReceiverParameter,
LexicalScopeKind.SYNTHETIC
) {
descriptor.declaredTypeParameters.forEach { addClassifierDescriptor(it) } descriptor.declaredTypeParameters.forEach { addClassifierDescriptor(it) }
descriptor.constructors.forEach { addFunctionDescriptor(it) } descriptor.constructors.forEach { addFunctionDescriptor(it) }
} }
val scopeChain = listOfNotNull( val scopeChain = listOfNotNull(
descriptor.defaultType.memberScope, descriptor.defaultType.memberScope,
descriptor.staticScope, descriptor.staticScope,
descriptor.companionObjectDescriptor?.defaultType?.memberScope descriptor.companionObjectDescriptor?.defaultType?.memberScope
) )
return LexicalChainedScope(headerScope, descriptor, false, null, LexicalScopeKind.SYNTHETIC, scopeChain) return LexicalChainedScope(headerScope, descriptor, false, null, LexicalScopeKind.SYNTHETIC, scopeChain)
} }
@@ -180,9 +175,10 @@ fun getKDocLinkResolutionScope(resolutionFacade: ResolutionFacade, contextDescri
is ClassDescriptor -> is ClassDescriptor ->
getClassInnerScope(getOuterScope(contextDescriptor, resolutionFacade), contextDescriptor) getClassInnerScope(getOuterScope(contextDescriptor, resolutionFacade), contextDescriptor)
is FunctionDescriptor -> is FunctionDescriptor -> FunctionDescriptorUtil.getFunctionInnerScope(
FunctionDescriptorUtil.getFunctionInnerScope(getOuterScope(contextDescriptor, resolutionFacade), getOuterScope(contextDescriptor, resolutionFacade),
contextDescriptor, LocalRedeclarationChecker.DO_NOTHING) contextDescriptor, LocalRedeclarationChecker.DO_NOTHING
)
is PropertyDescriptor -> is PropertyDescriptor ->
ScopeUtils.makeScopeForPropertyHeader(getOuterScope(contextDescriptor, resolutionFacade), contextDescriptor) ScopeUtils.makeScopeForPropertyHeader(getOuterScope(contextDescriptor, resolutionFacade), contextDescriptor)
@@ -197,13 +193,14 @@ fun getKDocLinkResolutionScope(resolutionFacade: ResolutionFacade, contextDescri
private fun getOuterScope(descriptor: DeclarationDescriptorWithSource, resolutionFacade: ResolutionFacade): LexicalScope { private fun getOuterScope(descriptor: DeclarationDescriptorWithSource, resolutionFacade: ResolutionFacade): LexicalScope {
val parent = descriptor.containingDeclaration!! val parent = descriptor.containingDeclaration!!
if (parent is PackageFragmentDescriptor) { if (parent is PackageFragmentDescriptor) {
val containingFile = (descriptor.source as? PsiSourceElement)?.psi?.containingFile as? KtFile val containingFile = (descriptor.source as? PsiSourceElement)?.psi?.containingFile as? KtFile ?: return LexicalScope.Base(
?: return LexicalScope.Base(ImportingScope.Empty, parent) ImportingScope.Empty,
parent
)
val kotlinCacheService = ServiceManager.getService(containingFile.project, KotlinCacheService::class.java) val kotlinCacheService = ServiceManager.getService(containingFile.project, KotlinCacheService::class.java)
val facadeToUse = kotlinCacheService?.getResolutionFacade(listOf(containingFile)) ?: resolutionFacade val facadeToUse = kotlinCacheService?.getResolutionFacade(listOf(containingFile)) ?: resolutionFacade
return facadeToUse.getFileResolutionScope(containingFile) return facadeToUse.getFileResolutionScope(containingFile)
} } else {
else {
return getKDocLinkResolutionScope(resolutionFacade, parent) return getKDocLinkResolutionScope(resolutionFacade, parent)
} }
} }
@@ -215,12 +212,14 @@ fun getKDocLinkMemberScope(descriptor: DeclarationDescriptor, contextScope: Lexi
is PackageViewDescriptor -> descriptor.memberScope is PackageViewDescriptor -> descriptor.memberScope
is ClassDescriptor -> { is ClassDescriptor -> {
ChainedMemberScope("Member scope for KDoc resolve", listOfNotNull( ChainedMemberScope(
"Member scope for KDoc resolve", listOfNotNull(
descriptor.unsubstitutedMemberScope, descriptor.unsubstitutedMemberScope,
descriptor.staticScope, descriptor.staticScope,
descriptor.companionObjectDescriptor?.unsubstitutedMemberScope, descriptor.companionObjectDescriptor?.unsubstitutedMemberScope,
ExtensionsScope(descriptor, contextScope) ExtensionsScope(descriptor, contextScope)
)) )
)
} }
else -> MemberScope.Empty else -> MemberScope.Empty
@@ -228,40 +227,53 @@ fun getKDocLinkMemberScope(descriptor: DeclarationDescriptor, contextScope: Lexi
} }
private class ExtensionsScope( private class ExtensionsScope(
private val receiverClass: ClassDescriptor, private val receiverClass: ClassDescriptor,
private val contextScope: LexicalScope private val contextScope: LexicalScope
) : MemberScope { ) : MemberScope {
private val receiverTypes = listOf(receiverClass.defaultType) private val receiverTypes = listOf(receiverClass.defaultType)
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<SimpleFunctionDescriptor> { override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<SimpleFunctionDescriptor> {
return contextScope.collectFunctions(name, location) return contextScope.collectFunctions(name, location).flatMap {
.flatMap { if (it is SimpleFunctionDescriptor && it.isExtension) it.substituteExtensionIfCallable(receiverTypes, CallType.DOT) else emptyList() } if (it is SimpleFunctionDescriptor && it.isExtension) it.substituteExtensionIfCallable(
receiverTypes,
CallType.DOT
) else emptyList()
}
} }
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> { override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
return contextScope.collectVariables(name, location) return contextScope.collectVariables(name, location).flatMap {
.flatMap { if (it is PropertyDescriptor && it.isExtension) it.substituteExtensionIfCallable(receiverTypes, CallType.DOT) else emptyList() } if (it is PropertyDescriptor && it.isExtension) it.substituteExtensionIfCallable(
receiverTypes,
CallType.DOT
) else emptyList()
}
} }
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = null 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() if (DescriptorKindExclude.Extensions in kindFilter.excludes) return emptyList()
return contextScope.collectDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.NonExtensions, nameFilter, changeNamesForAliased = true) return contextScope.collectDescriptorsFiltered(
.flatMap { if (it is CallableDescriptor && it.isExtension) it.substituteExtensionIfCallable(receiverTypes, CallType.DOT) else emptyList() } 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> { override fun getFunctionNames(): Set<Name> =
return getContributedDescriptors(kindFilter = DescriptorKindFilter.FUNCTIONS) getContributedDescriptors(kindFilter = DescriptorKindFilter.FUNCTIONS).map { it.name }.toSet()
.map { it.name }
.toSet()
}
override fun getVariableNames(): Set<Name> { override fun getVariableNames(): Set<Name> =
return getContributedDescriptors(kindFilter = DescriptorKindFilter.VARIABLES) getContributedDescriptors(kindFilter = DescriptorKindFilter.VARIABLES).map { it.name }.toSet()
.map { it.name }
.toSet()
}
override fun getClassifierNames() = null override fun getClassifierNames() = null
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.refactoring.introduce package org.jetbrains.kotlin.idea.refactoring.introduce
@@ -35,11 +24,11 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
class ExtractableSubstringInfo( class ExtractableSubstringInfo(
val startEntry: KtStringTemplateEntry, val startEntry: KtStringTemplateEntry,
val endEntry: KtStringTemplateEntry, val endEntry: KtStringTemplateEntry,
val prefix: String, val prefix: String,
val suffix: String, val suffix: String,
type: KotlinType? = null type: KotlinType? = null
) { ) {
private fun guessLiteralType(literal: String): KotlinType { private fun guessLiteralType(literal: String): KotlinType {
val facade = template.getResolutionFacade() val facade = template.getResolutionFacade()
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.resolve package org.jetbrains.kotlin.idea.resolve
@@ -51,8 +40,6 @@ interface ResolutionFacade {
} }
inline fun <reified T : Any> ResolutionFacade.frontendService(): T inline fun <reified T : Any> ResolutionFacade.frontendService(): T = this.getFrontendService(T::class.java)
= this.getFrontendService(T::class.java)
inline fun <reified T : Any> ResolutionFacade.ideService(): T inline fun <reified T : Any> ResolutionFacade.ideService(): T = this.getIdeService(T::class.java)
= this.getIdeService(T::class.java)
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.util package org.jetbrains.kotlin.idea.util
@@ -146,7 +135,8 @@ sealed class CallTypeAndReceiver<TReceiver : KtElement?, out TCallType : CallTyp
CallType.IMPORT_DIRECTIVE, receiver 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 TYPE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.TYPE>(CallType.TYPE, receiver)
class DELEGATE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.DELEGATE>(CallType.DELEGATE, receiver) class DELEGATE(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.DELEGATE>(CallType.DELEGATE, receiver)
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
@file:JvmName("FuzzyTypeUtils") @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.*
import org.jetbrains.kotlin.types.checker.StrictEqualityTypeChecker import org.jetbrains.kotlin.types.checker.StrictEqualityTypeChecker
import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.types.typeUtil.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.util.* import java.util.*
fun CallableDescriptor.fuzzyReturnType() = returnType?.toFuzzyType(typeParameters) fun CallableDescriptor.fuzzyReturnType() = returnType?.toFuzzyType(typeParameters)
@@ -67,8 +55,8 @@ fun FuzzyType.presentationType(): KotlinType {
fun KotlinType.toFuzzyType(freeParameters: Collection<TypeParameterDescriptor>) = FuzzyType(this, freeParameters) fun KotlinType.toFuzzyType(freeParameters: Collection<TypeParameterDescriptor>) = FuzzyType(this, freeParameters)
class FuzzyType( class FuzzyType(
val type: KotlinType, val type: KotlinType,
freeParameters: Collection<TypeParameterDescriptor> freeParameters: Collection<TypeParameterDescriptor>
) { ) {
val freeParameters: Set<TypeParameterDescriptor> val freeParameters: Set<TypeParameterDescriptor>
@@ -79,12 +67,10 @@ class FuzzyType(
if (usedTypeParameters.isNotEmpty()) { if (usedTypeParameters.isNotEmpty()) {
val originalFreeParameters = freeParameters.map { it.toOriginal() }.toSet() val originalFreeParameters = freeParameters.map { it.toOriginal() }.toSet()
this.freeParameters = usedTypeParameters.filter { it.toOriginal() in originalFreeParameters }.toSet() this.freeParameters = usedTypeParameters.filter { it.toOriginal() in originalFreeParameters }.toSet()
} } else {
else {
this.freeParameters = emptySet() this.freeParameters = emptySet()
} }
} } else {
else {
this.freeParameters = emptySet() this.freeParameters = emptySet()
} }
} }
@@ -115,17 +101,13 @@ class FuzzyType(
} }
} }
fun checkIsSubtypeOf(otherType: FuzzyType): TypeSubstitutor? fun checkIsSubtypeOf(otherType: FuzzyType): TypeSubstitutor? = matchedSubstitutor(otherType, MatchKind.IS_SUBTYPE)
= matchedSubstitutor(otherType, MatchKind.IS_SUBTYPE)
fun checkIsSuperTypeOf(otherType: FuzzyType): TypeSubstitutor? fun checkIsSuperTypeOf(otherType: FuzzyType): TypeSubstitutor? = matchedSubstitutor(otherType, MatchKind.IS_SUPERTYPE)
= matchedSubstitutor(otherType, MatchKind.IS_SUPERTYPE)
fun checkIsSubtypeOf(otherType: KotlinType): TypeSubstitutor? fun checkIsSubtypeOf(otherType: KotlinType): TypeSubstitutor? = checkIsSubtypeOf(otherType.toFuzzyType(emptyList()))
= checkIsSubtypeOf(otherType.toFuzzyType(emptyList()))
fun checkIsSuperTypeOf(otherType: KotlinType): TypeSubstitutor? fun checkIsSuperTypeOf(otherType: KotlinType): TypeSubstitutor? = checkIsSuperTypeOf(otherType.toFuzzyType(emptyList()))
= checkIsSuperTypeOf(otherType.toFuzzyType(emptyList()))
private enum class MatchKind { private enum class MatchKind {
IS_SUBTYPE, IS_SUBTYPE,
@@ -181,14 +163,14 @@ class FuzzyType(
}.buildSubstitutor() }.buildSubstitutor()
val substitutionMap: Map<TypeConstructor, TypeProjection> = constraintSystem.typeVariables val substitutionMap: Map<TypeConstructor, TypeProjection> = constraintSystem.typeVariables
.map { it.originalTypeParameter } .map { it.originalTypeParameter }
.associateBy( .associateBy(
keySelector = { it.typeConstructor }, keySelector = { it.typeConstructor },
valueTransform = { valueTransform = {
val typeProjection = TypeProjectionImpl(Variance.INVARIANT, it.defaultType) val typeProjection = TypeProjectionImpl(Variance.INVARIANT, it.defaultType)
val substitutedProjection = substitutorToKeepCapturedTypes.substitute(typeProjection) val substitutedProjection = substitutorToKeepCapturedTypes.substitute(typeProjection)
substitutedProjection?.takeUnless { ErrorUtils.containsUninferredParameter(it.type) } ?: typeProjection substitutedProjection?.takeUnless { ErrorUtils.containsUninferredParameter(it.type) } ?: typeProjection
}) })
return TypeConstructorSubstitution.createByConstructorsMap(substitutionMap, approximateCapturedTypes = true).buildSubstitutor() return TypeConstructorSubstitution.createByConstructorsMap(substitutionMap, approximateCapturedTypes = true).buildSubstitutor()
} }
} }
@@ -199,7 +181,10 @@ fun TypeSubstitution.hasConflictWith(other: TypeSubstitution, freeParameters: Co
val type = parameter.defaultType val type = parameter.defaultType
val substituted1 = this[type] ?: return@any false val substituted1 = this[type] ?: return@any false
val substituted2 = other[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. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.util package org.jetbrains.kotlin.idea.util
@@ -33,11 +22,16 @@ abstract class ImportInsertHelper {
abstract val importSortComparator: Comparator<ImportPath> 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 { companion object {
@JvmStatic fun getInstance(project: Project): ImportInsertHelper @JvmStatic
= ServiceManager.getService<ImportInsertHelper>(project, ImportInsertHelper::class.java) fun getInstance(project: Project): ImportInsertHelper =
ServiceManager.getService<ImportInsertHelper>(project, ImportInsertHelper::class.java)
} }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.util package org.jetbrains.kotlin.idea.util
@@ -29,4 +18,4 @@ fun FunctionDescriptor.shouldNotConvertToProperty(notProperties: Set<FqNameUnsaf
} }
fun SyntheticJavaPropertyDescriptor.suppressedByNotPropertyList(set: Set<FqNameUnsafe>) = 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. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.util package org.jetbrains.kotlin.idea.util
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
@@ -40,17 +28,17 @@ import org.jetbrains.kotlin.util.descriptorsEqualWithSubstitution
import java.util.* import java.util.*
class ShadowedDeclarationsFilter( class ShadowedDeclarationsFilter(
private val bindingContext: BindingContext, private val bindingContext: BindingContext,
private val resolutionFacade: ResolutionFacade, private val resolutionFacade: ResolutionFacade,
private val context: PsiElement, private val context: PsiElement,
private val explicitReceiverValue: ReceiverValue? private val explicitReceiverValue: ReceiverValue?
) { ) {
companion object { companion object {
fun create( fun create(
bindingContext: BindingContext, bindingContext: BindingContext,
resolutionFacade: ResolutionFacade, resolutionFacade: ResolutionFacade,
context: PsiElement, context: PsiElement,
callTypeAndReceiver: CallTypeAndReceiver<*, *> callTypeAndReceiver: CallTypeAndReceiver<*, *>
): ShadowedDeclarationsFilter? { ): ShadowedDeclarationsFilter? {
val receiverExpression = when (callTypeAndReceiver) { val receiverExpression = when (callTypeAndReceiver) {
is CallTypeAndReceiver.DEFAULT -> null is CallTypeAndReceiver.DEFAULT -> null
@@ -73,20 +61,16 @@ class ShadowedDeclarationsFilter(
private val psiFactory = KtPsiFactory(resolutionFacade.project) private val psiFactory = KtPsiFactory(resolutionFacade.project)
private val dummyExpressionFactory = DummyExpressionFactory(psiFactory) private val dummyExpressionFactory = DummyExpressionFactory(psiFactory)
fun <TDescriptor : DeclarationDescriptor> filter(declarations: Collection<TDescriptor>): Collection<TDescriptor> { fun <TDescriptor : DeclarationDescriptor> filter(declarations: Collection<TDescriptor>): Collection<TDescriptor> =
return declarations declarations.groupBy { signature(it) }.values.flatMap { group -> filterEqualSignatureGroup(group) }
.groupBy { signature(it) }
.values
.flatMap { group -> filterEqualSignatureGroup(group) }
}
fun <TDescriptor : DeclarationDescriptor> createNonImportedDeclarationsFilter( fun <TDescriptor : DeclarationDescriptor> createNonImportedDeclarationsFilter(
importedDeclarations: Collection<DeclarationDescriptor> importedDeclarations: Collection<DeclarationDescriptor>
): (Collection<TDescriptor>) -> Collection<TDescriptor> { ): (Collection<TDescriptor>) -> Collection<TDescriptor> {
val importedDeclarationsSet = importedDeclarations.toSet() val importedDeclarationsSet = importedDeclarations.toSet()
val importedDeclarationsBySignature = importedDeclarationsSet.groupBy { signature(it) } val importedDeclarationsBySignature = importedDeclarationsSet.groupBy { signature(it) }
return filter@ { declarations -> return filter@{ declarations ->
// optimization // optimization
if (declarations.size == 1 && importedDeclarationsBySignature[signature(declarations.single())] == null) return@filter declarations if (declarations.size == 1 && importedDeclarationsBySignature[signature(declarations.single())] == null) return@filter declarations
@@ -103,19 +87,18 @@ class ShadowedDeclarationsFilter(
} }
} }
private fun signature(descriptor: DeclarationDescriptor): Any = private fun signature(descriptor: DeclarationDescriptor): Any = when (descriptor) {
when (descriptor) { is SimpleFunctionDescriptor -> FunctionSignature(descriptor)
is SimpleFunctionDescriptor -> FunctionSignature(descriptor) is VariableDescriptor -> descriptor.name
is VariableDescriptor -> descriptor.name is ClassDescriptor -> descriptor.importableFqName ?: descriptor
is ClassDescriptor -> descriptor.importableFqName ?: descriptor else -> descriptor
else -> descriptor }
}
private fun packageName(descriptor: DeclarationDescriptor) = descriptor.importableFqName?.parent() private fun packageName(descriptor: DeclarationDescriptor) = descriptor.importableFqName?.parent()
private fun <TDescriptor : DeclarationDescriptor> filterEqualSignatureGroup( private fun <TDescriptor : DeclarationDescriptor> filterEqualSignatureGroup(
descriptors: Collection<TDescriptor>, descriptors: Collection<TDescriptor>,
descriptorsToImport: Collection<TDescriptor> = emptyList() descriptorsToImport: Collection<TDescriptor> = emptyList()
): Collection<TDescriptor> { ): Collection<TDescriptor> {
if (descriptors.size == 1) return descriptors if (descriptors.size == 1) return descriptors
@@ -143,7 +126,8 @@ class ShadowedDeclarationsFilter(
} }
val firstVarargIndex = parameters.withIndex().firstOrNull { it.value.varargElementType != null }?.index 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 { class DummyArgument(val index: Int) : ValueArgument {
private val expression = dummyArgumentExpressions[index] private val expression = dummyArgumentExpressions[index]
@@ -153,8 +137,7 @@ class ShadowedDeclarationsFilter(
override val asName = parameters[index].name override val asName = parameters[index].name
override val referenceExpression = null override val referenceExpression = null
} }
} } else {
else {
null null
} }
@@ -206,17 +189,23 @@ class ShadowedDeclarationsFilter(
} }
val dataFlowInfo = bindingContext.getDataFlowInfoBefore(context) val dataFlowInfo = bindingContext.getDataFlowInfoBefore(context)
val context = BasicCallResolutionContext.create(bindingTrace, scope, newCall, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo, val context = BasicCallResolutionContext.create(
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, bindingTrace, scope, newCall, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo,
false, /* languageVersionSettings */ resolutionFacade.frontendService(), ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
resolutionFacade.frontendService<DataFlowValueFactory>()) false, /* languageVersionSettings */ resolutionFacade.frontendService(),
resolutionFacade.frontendService<DataFlowValueFactory>()
)
val callResolver = resolutionFacade.frontendService<CallResolver>() val callResolver = resolutionFacade.frontendService<CallResolver>()
val results = if (isFunction) callResolver.resolveFunctionCall(context) else callResolver.resolveSimpleProperty(context) val results = if (isFunction) callResolver.resolveFunctionCall(context) else callResolver.resolveSimpleProperty(context)
val resultingDescriptors = results.resultingCalls.map { it.resultingDescriptor } val resultingDescriptors = results.resultingCalls.map { it.resultingDescriptor }
val resultingOriginals = resultingDescriptors.mapTo(HashSet<DeclarationDescriptor>()) { it.original } val resultingOriginals = resultingDescriptors.mapTo(HashSet<DeclarationDescriptor>()) { it.original }
val filtered = descriptors.filter { candidateDescriptor -> val filtered = descriptors.filter { candidateDescriptor ->
candidateDescriptor.original in resultingOriginals /* optimization */ candidateDescriptor.original in resultingOriginals /* optimization */ && resultingDescriptors.any {
&& resultingDescriptors.any { descriptorsEqualWithSubstitution(it, candidateDescriptor) } 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 */ 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. * 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.
* 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.
*/ */
@file:JvmName("TypeUtils") @file:JvmName("TypeUtils")
@@ -69,9 +58,8 @@ private fun KotlinType.approximateNonDynamicFlexibleTypes(
approximation = if (nullability() == TypeNullability.NOT_NULL) approximation.makeNullableAsSpecified(false) else approximation approximation = if (nullability() == TypeNullability.NOT_NULL) approximation.makeNullableAsSpecified(false) else approximation
if (approximation.isMarkedNullable && !flexible.lowerBound.isMarkedNullable && TypeUtils.isTypeParameter(approximation) && TypeUtils.hasNullableSuperType( if (approximation.isMarkedNullable && !flexible.lowerBound
approximation .isMarkedNullable && TypeUtils.isTypeParameter(approximation) && TypeUtils.hasNullableSuperType(approximation)
)
) { ) {
approximation = approximation.makeNullableAsSpecified(false) approximation = approximation.makeNullableAsSpecified(false)
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.util package org.jetbrains.kotlin.idea.util
@@ -56,14 +45,21 @@ fun KtFunctionLiteral.findLabelAndCall(): Pair<Name?, KtCallExpression?> {
} }
fun SmartCastManager.getSmartCastVariantsWithLessSpecificExcluded( fun SmartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
receiverToCast: ReceiverValue, receiverToCast: ReceiverValue,
bindingContext: BindingContext, bindingContext: BindingContext,
containingDeclarationOrModule: DeclarationDescriptor, containingDeclarationOrModule: DeclarationDescriptor,
dataFlowInfo: DataFlowInfo, dataFlowInfo: DataFlowInfo,
languageVersionSettings: LanguageVersionSettings, languageVersionSettings: LanguageVersionSettings,
dataFlowValueFactory: DataFlowValueFactory dataFlowValueFactory: DataFlowValueFactory
): List<KotlinType> { ): List<KotlinType> {
val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo, languageVersionSettings, dataFlowValueFactory) val variants = getSmartCastVariants(
receiverToCast,
bindingContext,
containingDeclarationOrModule,
dataFlowInfo,
languageVersionSettings,
dataFlowValueFactory
)
return variants.filter { type -> return variants.filter { type ->
variants.all { another -> another === type || chooseMoreSpecific(type, another).let { it == null || it === 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. * 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.
* 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.
*/ */
@file:JvmName("ExtensionUtils") @file:JvmName("ExtensionUtils")
@@ -33,8 +22,8 @@ import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.nullability import org.jetbrains.kotlin.types.typeUtil.nullability
fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable( fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
receiverTypes: Collection<KotlinType>, receiverTypes: Collection<KotlinType>,
callType: CallType<*> callType: CallType<*>
): Collection<TCallable> { ): Collection<TCallable> {
if (!callType.descriptorKindFilter.accepts(this)) return listOf() if (!callType.descriptorKindFilter.accepts(this)) return listOf()
@@ -44,22 +33,20 @@ fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
} }
val extensionReceiverType = fuzzyExtensionReceiverType()!! val extensionReceiverType = fuzzyExtensionReceiverType()!!
val substitutors = types val substitutors = types.mapNotNull {
.mapNotNull { var substitutor = extensionReceiverType.checkIsSuperTypeOf(it)
var substitutor = extensionReceiverType.checkIsSuperTypeOf(it) // check if we may fail due to receiver expression being nullable
// check if we may fail due to receiver expression being nullable if (substitutor == null && it.nullability() == TypeNullability.NULLABLE && extensionReceiverType.nullability() == TypeNullability.NOT_NULL) {
if (substitutor == null && it.nullability() == TypeNullability.NULLABLE && extensionReceiverType.nullability() == TypeNullability.NOT_NULL) { substitutor = extensionReceiverType.checkIsSuperTypeOf(it.makeNotNullable())
substitutor = extensionReceiverType.checkIsSuperTypeOf(it.makeNotNullable()) }
} substitutor
substitutor }
}
return if (typeParameters.isEmpty()) { // optimization for non-generic callables return if (typeParameters.isEmpty()) { // optimization for non-generic callables
if (substitutors.any()) listOf(this) else listOf() if (substitutors.any()) listOf(this) else listOf()
} } else {
else {
substitutors substitutors
.mapNotNull { @Suppress("UNCHECKED_CAST") (substitute(it) as TCallable?) } .mapNotNull { @Suppress("UNCHECKED_CAST") (substitute(it) as TCallable?) }
.toList() .toList()
} }
} }
@@ -76,20 +63,16 @@ fun ReceiverValue?.getThisReceiverOwner(bindingContext: BindingContext): Declara
} }
} }
fun ReceiverValue?.getReceiverTargetDescriptor(bindingContext: BindingContext): DeclarationDescriptor? { fun ReceiverValue?.getReceiverTargetDescriptor(bindingContext: BindingContext): DeclarationDescriptor? = when (this) {
return when (this) { is ExpressionReceiver -> when (val expression = KtPsiUtil.deparenthesize(this.expression)) {
is ExpressionReceiver -> { is KtThisExpression -> expression.instanceReference
val expression = KtPsiUtil.deparenthesize(this.expression) is KtReferenceExpression -> 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
else -> null 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. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.util package org.jetbrains.kotlin.idea.util
@@ -42,14 +31,10 @@ interface ReceiverExpressionFactory {
fun createExpression(psiFactory: KtPsiFactory, shortThis: Boolean = true): KtExpression fun createExpression(psiFactory: KtPsiFactory, shortThis: Boolean = true): KtExpression
} }
fun LexicalScope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType: KotlinType): ReceiverExpressionFactory? { fun LexicalScope.getFactoryForImplicitReceiverWithSubtypeOf(receiverType: KotlinType): ReceiverExpressionFactory? =
return getImplicitReceiversWithInstanceToExpression() getImplicitReceiversWithInstanceToExpression().entries.firstOrNull { (receiverDescriptor, _) ->
.entries receiverDescriptor.type.isSubtypeOf(receiverType)
.firstOrNull { (receiverDescriptor, _) -> }?.value
receiverDescriptor.type.isSubtypeOf(receiverType)
}
?.value
}
fun LexicalScope.getImplicitReceiversWithInstanceToExpression( fun LexicalScope.getImplicitReceiversWithInstanceToExpression(
excludeShadowedByDslMarkers: Boolean = false excludeShadowedByDslMarkers: Boolean = false
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.util.psi.patternMatching package org.jetbrains.kotlin.idea.util.psi.patternMatching
@@ -34,7 +23,7 @@ interface KotlinPsiRange {
override fun getTextRange(): TextRange = TextRange.EMPTY_RANGE 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 startElement: PsiElement = elements.first()
val endElement: PsiElement = elements.last() val endElement: PsiElement = elements.last()
@@ -63,29 +52,28 @@ interface KotlinPsiRange {
val matches = ArrayList<UnificationResult.Matched>() val matches = ArrayList<UnificationResult.Matched>()
scope.accept( scope.accept(
object: KtTreeVisitorVoid() { object : KtTreeVisitorVoid() {
override fun visitKtElement(element: KtElement) { override fun visitKtElement(element: KtElement) {
val range = element val range = element
.siblings() .siblings()
.filter(SIGNIFICANT_FILTER) .filter(SIGNIFICANT_FILTER)
.take(elements.size) .take(elements.size)
.toList() .toList()
.toRange() .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) matches.add(result)
} }
else {
val matchCountSoFar = matches.size
super.visitKtElement(element)
if (result is UnificationResult.WeaklyMatched && matches.size == matchCountSoFar) {
matches.add(result)
}
}
} }
} }
}
) )
return matches return matches
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.util.psi.patternMatching package org.jetbrains.kotlin.idea.util.psi.patternMatching
@@ -71,43 +60,43 @@ interface UnificationResult {
override val status: Status get() = UNMATCHED override val status: Status get() = UNMATCHED
} }
interface Matched: UnificationResult { interface Matched : UnificationResult {
val range: KotlinPsiRange val range: KotlinPsiRange
val substitution: Map<UnifierParameter, KtElement> val substitution: Map<UnifierParameter, KtElement>
override val status: Status get() = MATCHED override val status: Status get() = MATCHED
} }
class StronglyMatched( class StronglyMatched(
override val range: KotlinPsiRange, override val range: KotlinPsiRange,
override val substitution: Map<UnifierParameter, KtElement> override val substitution: Map<UnifierParameter, KtElement>
): Matched ) : Matched
class WeaklyMatched( class WeaklyMatched(
override val range: KotlinPsiRange, override val range: KotlinPsiRange,
override val substitution: Map<UnifierParameter, KtElement>, override val substitution: Map<UnifierParameter, KtElement>,
val weakMatches: Map<KtElement, KtElement> val weakMatches: Map<KtElement, KtElement>
): Matched ) : Matched
val status: Status val status: Status
val matched: Boolean get() = status != UNMATCHED val matched: Boolean get() = status != UNMATCHED
} }
class UnifierParameter( class UnifierParameter(
val descriptor: DeclarationDescriptor, val descriptor: DeclarationDescriptor,
val expectedType: KotlinType? val expectedType: KotlinType?
) )
class KotlinPsiUnifier( class KotlinPsiUnifier(
parameters: Collection<UnifierParameter> = Collections.emptySet(), parameters: Collection<UnifierParameter> = Collections.emptySet(),
val allowWeakMatches: Boolean = false val allowWeakMatches: Boolean = false
) { ) {
companion object { companion object {
val DEFAULT = KotlinPsiUnifier() val DEFAULT = KotlinPsiUnifier()
} }
private inner class Context( private inner class Context(
val originalTarget: KotlinPsiRange, val originalTarget: KotlinPsiRange,
val originalPattern: KotlinPsiRange val originalPattern: KotlinPsiRange
) { ) {
val patternContext: BindingContext = originalPattern.getBindingContext() val patternContext: BindingContext = originalPattern.getBindingContext()
val targetContext: BindingContext = originalTarget.getBindingContext() val targetContext: BindingContext = originalTarget.getBindingContext()
@@ -155,7 +144,7 @@ class KotlinPsiUnifier(
private fun matchCalls(call1: Call, call2: Call): Boolean { private fun matchCalls(call1: Call, call2: Call): Boolean {
return matchReceivers(call1.explicitReceiver, call2.explicitReceiver) && return matchReceivers(call1.explicitReceiver, call2.explicitReceiver) &&
matchReceivers(call1.dispatchReceiver, call2.dispatchReceiver) matchReceivers(call1.dispatchReceiver, call2.dispatchReceiver)
} }
private fun matchArguments(arg1: ValueArgument, arg2: ValueArgument): Status { private fun matchArguments(arg1: ValueArgument, arg2: ValueArgument): Status {
@@ -210,25 +199,23 @@ class KotlinPsiUnifier(
fun checkImplicitReceiver(implicitCall: ResolvedCall<*>, explicitCall: ResolvedCall<*>): Boolean { fun checkImplicitReceiver(implicitCall: ResolvedCall<*>, explicitCall: ResolvedCall<*>): Boolean {
val (implicitReceiver, explicitReceiver) = val (implicitReceiver, explicitReceiver) =
when (explicitCall.explicitReceiverKind) { when (explicitCall.explicitReceiverKind) {
ExplicitReceiverKind.EXTENSION_RECEIVER -> ExplicitReceiverKind.EXTENSION_RECEIVER ->
(implicitCall.extensionReceiver as? ImplicitReceiver) to (implicitCall.extensionReceiver as? ImplicitReceiver) to (explicitCall.extensionReceiver as? ExpressionReceiver)
(explicitCall.extensionReceiver as? ExpressionReceiver)
ExplicitReceiverKind.DISPATCH_RECEIVER -> ExplicitReceiverKind.DISPATCH_RECEIVER ->
(implicitCall.dispatchReceiver as? ImplicitReceiver) to (implicitCall.dispatchReceiver as? ImplicitReceiver) to (explicitCall.dispatchReceiver as? ExpressionReceiver)
(explicitCall.dispatchReceiver as? ExpressionReceiver)
else -> else ->
null to null null to null
} }
val thisExpression = explicitReceiver?.expression as? KtThisExpression val thisExpression = explicitReceiver?.expression as? KtThisExpression
if (implicitReceiver == null || thisExpression == null) return false if (implicitReceiver == null || thisExpression == null) return false
return matchDescriptors( return matchDescriptors(
implicitReceiver.declarationDescriptor, implicitReceiver.declarationDescriptor,
thisExpression.getAdjustedResolvedCall()?.candidateDescriptor?.containingDeclaration thisExpression.getAdjustedResolvedCall()?.candidateDescriptor?.containingDeclaration
) )
} }
@@ -236,7 +223,10 @@ class KotlinPsiUnifier(
return when { return when {
rc1.explicitReceiverKind == rc2.explicitReceiverKind -> { rc1.explicitReceiverKind == rc2.explicitReceiverKind -> {
matchReceivers(rc1.extensionReceiver, rc2.extensionReceiver) && 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) rc1.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER -> checkImplicitReceiver(rc1, rc2)
@@ -279,8 +269,7 @@ class KotlinPsiUnifier(
private fun KtElement.getAdjustedResolvedCall(): ResolvedCall<*>? { private fun KtElement.getAdjustedResolvedCall(): ResolvedCall<*>? {
val rc = if (this is KtArrayAccessExpression) { val rc = if (this is KtArrayAccessExpression) {
bindingContext[BindingContext.INDEXED_LVALUE_GET, this] bindingContext[BindingContext.INDEXED_LVALUE_GET, this]
} } else {
else {
getResolvedCall(bindingContext)?.let { getResolvedCall(bindingContext)?.let {
when { when {
it !is VariableAsFunctionResolvedCall -> it it !is VariableAsFunctionResolvedCall -> it
@@ -330,15 +319,20 @@ class KotlinPsiUnifier(
} }
private fun matchTypes( private fun matchTypes(
type1: KotlinType?, type1: KotlinType?,
type2: KotlinType?, type2: KotlinType?,
typeRef1: KtTypeReference? = null, typeRef1: KtTypeReference? = null,
typeRef2: KtTypeReference? = null typeRef2: KtTypeReference? = null
): Status? { ): Status? {
if (type1 != null && type2 != null) { if (type1 != null && type2 != null) {
val unwrappedType1 = type1.unwrap() val unwrappedType1 = type1.unwrap()
val unwrappedType2 = type2.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.isError || type2.isError) return null
if (type1 is AbbreviatedType != type2 is AbbreviatedType) return UNMATCHED if (type1 is AbbreviatedType != type2 is AbbreviatedType) return UNMATCHED
@@ -348,16 +342,18 @@ class KotlinPsiUnifier(
if (type1.isMarkedNullable != type2.isMarkedNullable) return UNMATCHED if (type1.isMarkedNullable != type2.isMarkedNullable) return UNMATCHED
if (!matchDescriptors( if (!matchDescriptors(
type1.constructor.declarationDescriptor, type1.constructor.declarationDescriptor,
type2.constructor.declarationDescriptor)) return UNMATCHED type2.constructor.declarationDescriptor
)
) return UNMATCHED
val args1 = type1.arguments val args1 = type1.arguments
val args2 = type2.arguments val args2 = type2.arguments
if (args1.size != args2.size) return UNMATCHED if (args1.size != args2.size) return UNMATCHED
if (!args1.withIndex().all { p -> if (!args1.withIndex().all { p ->
val (i, arg1) = p val (i, arg1) = p
val arg2 = args2[i] val arg2 = args2[i]
matchTypeArguments(i, arg1, arg2, typeRef1, typeRef2) matchTypeArguments(i, arg1, arg2, typeRef1, typeRef2)
}) return UNMATCHED }) return UNMATCHED
return MATCHED return MATCHED
} }
@@ -366,11 +362,11 @@ class KotlinPsiUnifier(
} }
private fun matchTypeArguments( private fun matchTypeArguments(
argIndex: Int, argIndex: Int,
arg1: TypeProjection, arg1: TypeProjection,
arg2: TypeProjection, arg2: TypeProjection,
typeRef1: KtTypeReference?, typeRef1: KtTypeReference?,
typeRef2: KtTypeReference? typeRef2: KtTypeReference?
): Boolean { ): Boolean {
val typeArgRef1 = typeRef1?.typeElement?.typeArgumentsAsTypes?.getOrNull(argIndex) val typeArgRef1 = typeRef1?.typeElement?.typeArgumentsAsTypes?.getOrNull(argIndex)
val typeArgRef2 = typeRef2?.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 status = if (!checkEquivalence && typeRef1 != null && typeRef2 != null) {
val typePsi1 = argType1.constructor.declarationDescriptor?.source?.getPsi() val typePsi1 = argType1.constructor.declarationDescriptor?.source?.getPsi()
val typePsi2 = argType2.constructor.declarationDescriptor?.source?.getPsi() val typePsi2 = argType2.constructor.declarationDescriptor?.source?.getPsi()
descriptorToParameter[typePsi1]?.let { substitute(it, typeArgRef2) } ?: descriptorToParameter[typePsi1]?.let { substitute(it, typeArgRef2) }
descriptorToParameter[typePsi2]?.let { substitute(it, typeArgRef1) } ?: ?: descriptorToParameter[typePsi2]?.let { substitute(it, typeArgRef1) }
matchTypes(argType1, argType2, typeArgRef1, typeArgRef2) ?: matchTypes(argType1, argType2, typeArgRef1, typeArgRef2)
} } else matchTypes(argType1, argType2, typeArgRef1, typeArgRef2)
else matchTypes(argType1, argType2, typeArgRef1, typeArgRef2)
return status == MATCHED return status == MATCHED
} }
@@ -413,12 +408,11 @@ class KotlinPsiUnifier(
else -> false else -> false
} }
private fun KtBinaryExpression.matchComplexAssignmentWithSimple(simple: KtBinaryExpression): Status? { private fun KtBinaryExpression.matchComplexAssignmentWithSimple(simple: KtBinaryExpression): Status? =
return when { when (doUnify(left, simple.left)) {
doUnify(left, simple.left) == UNMATCHED -> UNMATCHED UNMATCHED -> UNMATCHED
else -> simple.right?.let { matchCalls(this, it) } ?: UNMATCHED else -> simple.right?.let { matchCalls(this, it) } ?: UNMATCHED
} }
}
private fun KtBinaryExpression.matchAssignment(e: KtElement): Status? { private fun KtBinaryExpression.matchAssignment(e: KtElement): Status? {
val operationType = operationReference.getReferencedNameElementType() as KtToken val operationType = operationReference.getReferencedNameElementType() as KtToken
@@ -435,11 +429,13 @@ class KotlinPsiUnifier(
val setResolvedCall = bindingContext[BindingContext.INDEXED_LVALUE_SET, lhs] val setResolvedCall = bindingContext[BindingContext.INDEXED_LVALUE_SET, lhs]
val resolvedCallToMatch = e.getAdjustedResolvedCall() 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() val assignResolvedCall = getAdjustedResolvedCall() ?: return UNMATCHED
if (assignResolvedCall == null) return UNMATCHED
val operationName = OperatorConventions.getNameForOperationSymbol(operationType) val operationName = OperatorConventions.getNameForOperationSymbol(operationType)
if (assignResolvedCall.resultingDescriptor?.name == operationName) return matchCalls(this, e) if (assignResolvedCall.resultingDescriptor?.name == operationName) return matchCalls(this, e)
@@ -456,13 +452,11 @@ class KotlinPsiUnifier(
private fun PsiElement.isIncrement(): Boolean { private fun PsiElement.isIncrement(): Boolean {
val parent = parent val parent = parent
return parent is KtUnaryExpression return parent is KtUnaryExpression && this == parent.operationReference && ((parent.operationToken as KtToken) in OperatorConventions.INCREMENT_OPERATIONS)
&& this == parent.operationReference
&& ((parent.operationToken as KtToken) in OperatorConventions.INCREMENT_OPERATIONS)
} }
private fun KtCallableReferenceExpression.hasExpressionReceiver(): Boolean = 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? { private fun matchCallableReferences(e1: KtCallableReferenceExpression, e2: KtCallableReferenceExpression): Status? {
if (e1.hasExpressionReceiver() || e2.hasExpressionReceiver()) return null if (e1.hasExpressionReceiver() || e2.hasExpressionReceiver()) return null
@@ -510,10 +504,11 @@ class KotlinPsiUnifier(
} }
private fun matchCallables( private fun matchCallables(
decl1: KtDeclaration, decl1: KtDeclaration,
decl2: KtDeclaration, decl2: KtDeclaration,
desc1: CallableDescriptor, desc1: CallableDescriptor,
desc2: CallableDescriptor): Status? { desc2: CallableDescriptor
): Status? {
fun needToCompareReturnTypes(): Boolean { fun needToCompareReturnTypes(): Boolean {
if (decl1 !is KtCallableDeclaration) return true if (decl1 !is KtCallableDeclaration) return true
return decl1.typeReference != null || (decl2 as KtCallableDeclaration).typeReference != null return decl1.typeReference != null || (decl2 as KtCallableDeclaration).typeReference != null
@@ -527,8 +522,11 @@ class KotlinPsiUnifier(
val type1 = desc1.returnType val type1 = desc1.returnType
val type2 = desc2.returnType val type2 = desc2.returnType
if (type1 != type2 if (type1 != type2 && (type1 == null || type2 == null || type1.isError || type2.isError || matchTypes(
&& (type1 == null || type2 == null || type1.isError || type2.isError || matchTypes(type1, type2) != MATCHED)) { type1,
type2
) != MATCHED)
) {
return UNMATCHED return UNMATCHED
} }
} }
@@ -540,14 +538,14 @@ class KotlinPsiUnifier(
val params2 = desc2.valueParameters val params2 = desc2.valueParameters
val zippedParams = params1.zip(params2) val zippedParams = params1.zip(params2)
val parametersMatch = 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 if (!parametersMatch) return UNMATCHED
zippedParams.forEach { declarationPatternsToTargets.putValue(it.first, it.second) } zippedParams.forEach { declarationPatternsToTargets.putValue(it.first, it.second) }
return doUnify( return doUnify(
(decl1 as? KtTypeParameterListOwner)?.typeParameters?.toRange() ?: Empty, (decl1 as? KtTypeParameterListOwner)?.typeParameters?.toRange() ?: Empty,
(decl2 as? KtTypeParameterListOwner)?.typeParameters?.toRange() ?: Empty (decl2 as? KtTypeParameterListOwner)?.typeParameters?.toRange() ?: Empty
) and when (decl1) { ) and when (decl1) {
is KtDeclarationWithBody -> is KtDeclarationWithBody ->
doUnify(decl1.bodyExpression, (decl2 as KtDeclarationWithBody).bodyExpression) doUnify(decl1.bodyExpression, (decl2 as KtDeclarationWithBody).bodyExpression)
@@ -570,14 +568,19 @@ class KotlinPsiUnifier(
return parent is KtClassBody || parent is KtFile 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 return (!decl1.isNameRelevant() && !decl2.isNameRelevant()) || desc1.name == desc2.name
} }
private fun <T: DeclarationDescriptor> matchContainedDescriptors( private fun <T : DeclarationDescriptor> matchContainedDescriptors(
declarations1: List<T>, declarations1: List<T>,
declarations2: List<T>, declarations2: List<T>,
matchPair: (Pair<T, T>) -> Boolean matchPair: (Pair<T, T>) -> Boolean
): Boolean { ): Boolean {
val zippedParams = declarations1.zip(declarations2) val zippedParams = declarations1.zip(declarations2)
if (declarations1.size != declarations2.size || !zippedParams.all { matchPair(it) }) return false if (declarations1.size != declarations2.size || !zippedParams.all { matchPair(it) }) return false
@@ -587,13 +590,14 @@ class KotlinPsiUnifier(
} }
private fun matchClasses( private fun matchClasses(
decl1: KtClassOrObject, decl1: KtClassOrObject,
decl2: KtClassOrObject, decl2: KtClassOrObject,
desc1: ClassDescriptor, desc1: ClassDescriptor,
desc2: ClassDescriptor): Status? { desc2: ClassDescriptor
): Status? {
class OrderInfo<out T>( class OrderInfo<out T>(
val orderSensitive: List<T>, val orderSensitive: List<T>,
val orderInsensitive: List<T> val orderInsensitive: List<T>
) )
fun getMemberOrderInfo(cls: KtClassOrObject): OrderInfo<KtDeclaration> { fun getMemberOrderInfo(cls: KtClassOrObject): OrderInfo<KtDeclaration> {
@@ -610,9 +614,8 @@ class KotlinPsiUnifier(
} }
fun resolveAndSortDeclarationsByDescriptor(declarations: List<KtDeclaration>): List<Pair<KtDeclaration, DeclarationDescriptor?>> { fun resolveAndSortDeclarationsByDescriptor(declarations: List<KtDeclaration>): List<Pair<KtDeclaration, DeclarationDescriptor?>> {
return declarations return declarations.map { it to it.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it] }
.map { it to it.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, it] } .sortedBy { it.second?.let { descriptor -> IdeDescriptorRenderers.SOURCE_CODE.render(descriptor) } ?: "" }
.sortedBy { it.second?.let { IdeDescriptorRenderers.SOURCE_CODE.render(it) } ?: "" }
} }
fun sortDeclarationsByElementType(declarations: List<KtDeclaration>): List<KtDeclaration> { fun sortDeclarationsByElementType(declarations: List<KtDeclaration>): List<KtDeclaration> {
@@ -642,7 +645,10 @@ class KotlinPsiUnifier(
return UNMATCHED 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((decl1 as? KtClass)?.typeParameterList, (decl2 as? KtClass)?.typeParameterList) and
doUnify(delegationInfo1.orderSensitive.toRange(), delegationInfo2.orderSensitive.toRange()) doUnify(delegationInfo1.orderSensitive.toRange(), delegationInfo2.orderSensitive.toRange())
if (status == UNMATCHED) return UNMATCHED if (status == UNMATCHED) return UNMATCHED
@@ -654,19 +660,20 @@ class KotlinPsiUnifier(
val sortedMembers2 = resolveAndSortDeclarationsByDescriptor(membersInfo2.orderInsensitive) val sortedMembers2 = resolveAndSortDeclarationsByDescriptor(membersInfo2.orderInsensitive)
if ((sortedMembers1.size != sortedMembers2.size)) return UNMATCHED if ((sortedMembers1.size != sortedMembers2.size)) return UNMATCHED
if (sortedMembers1.zip(sortedMembers2).any { if (sortedMembers1.zip(sortedMembers2).any {
val (d1, d2) = it val (d1, d2) = it
(matchDeclarations(d1.first, d2.first, d1.second, d2.second) ?: doUnify(d1.first, d2.first)) == UNMATCHED (matchDeclarations(d1.first, d2.first, d1.second, d2.second) ?: doUnify(d1.first, d2.first)) == UNMATCHED
}) return UNMATCHED }
) return UNMATCHED
return doUnify( return doUnify(
sortDeclarationsByElementType(membersInfo1.orderSensitive).toRange(), sortDeclarationsByElementType(membersInfo1.orderSensitive).toRange(),
sortDeclarationsByElementType(membersInfo2.orderSensitive).toRange() sortDeclarationsByElementType(membersInfo2.orderSensitive).toRange()
) )
} }
private fun matchTypeParameters( private fun matchTypeParameters(
desc1: TypeParameterDescriptor, desc1: TypeParameterDescriptor,
desc2: TypeParameterDescriptor desc2: TypeParameterDescriptor
): Status { ): Status {
if (desc1.variance != desc2.variance) return UNMATCHED if (desc1.variance != desc2.variance) return UNMATCHED
if (!matchTypes(desc1.upperBounds, desc2.upperBounds)) return UNMATCHED if (!matchTypes(desc1.upperBounds, desc2.upperBounds)) return UNMATCHED
@@ -682,18 +689,22 @@ class KotlinPsiUnifier(
} }
private fun matchDeclarations( private fun matchDeclarations(
decl1: KtDeclaration, decl1: KtDeclaration,
decl2: KtDeclaration, decl2: KtDeclaration,
desc1: DeclarationDescriptor?, desc1: DeclarationDescriptor?,
desc2: DeclarationDescriptor?): Status? { desc2: DeclarationDescriptor?
): Status? {
if (decl1::class.java != decl2::class.java) return UNMATCHED if (decl1::class.java != decl2::class.java) return UNMATCHED
if (desc1 == null || desc2 == null) { if (desc1 == null || desc2 == null) {
if (decl1 is KtParameter return if (decl1 is KtParameter
&& decl2 is KtParameter && decl2 is KtParameter
&& decl1.getStrictParentOfType<KtTypeElement>() != null && decl1.getStrictParentOfType<KtTypeElement>() != null
&& decl2.getStrictParentOfType<KtTypeElement>() != null) return null && decl2.getStrictParentOfType<KtTypeElement>() != null
return UNMATCHED )
null
else
UNMATCHED
} }
if (ErrorUtils.isError(desc1) || ErrorUtils.isError(desc2)) return UNMATCHED if (ErrorUtils.isError(desc1) || ErrorUtils.isError(desc2)) return UNMATCHED
if (desc1::class.java != desc2::class.java) return UNMATCHED if (desc1::class.java != desc2::class.java) return UNMATCHED
@@ -801,8 +812,7 @@ class KotlinPsiUnifier(
val patternText = pattern.startEntry.text.substring(prefixLength) val patternText = pattern.startEntry.text.substring(prefixLength)
if (!targetEntryText.endsWith(patternText)) continue if (!targetEntryText.endsWith(patternText)) continue
targetEntryText.substring(0, targetEntryText.length - patternText.length) targetEntryText.substring(0, targetEntryText.length - patternText.length)
} } else ""
else ""
val lastTargetEntry = targetEntries[index + patternEntries.lastIndex] val lastTargetEntry = targetEntries[index + patternEntries.lastIndex]
@@ -813,8 +823,7 @@ class KotlinPsiUnifier(
val lastTargetEntryText = lastTargetEntry.text val lastTargetEntryText = lastTargetEntry.text
if (!lastTargetEntryText.startsWith(patternText)) continue if (!lastTargetEntryText.startsWith(patternText)) continue
lastTargetEntryText.substring(patternText.length) lastTargetEntryText.substring(patternText.length)
} } else ""
else ""
val fromIndex = if (matchStartByText) 1 else 0 val fromIndex = if (matchStartByText) 1 else 0
val toIndex = if (matchEndByText) patternEntries.lastIndex - 1 else patternEntries.lastIndex val toIndex = if (matchEndByText) patternEntries.lastIndex - 1 else patternEntries.lastIndex
@@ -846,8 +855,7 @@ class KotlinPsiUnifier(
} }
} }
private fun ASTNode.getChildrenRange(): KotlinPsiRange = private fun ASTNode.getChildrenRange(): KotlinPsiRange = getChildren(null).mapNotNull { it.psi }.toRange()
getChildren(null).mapNotNull { it.psi }.toRange()
private fun PsiElement.unwrapWeakly(): KtElement? { private fun PsiElement.unwrapWeakly(): KtElement? {
return when { return when {
@@ -860,8 +868,8 @@ class KotlinPsiUnifier(
} }
private fun doUnifyWeakly( private fun doUnifyWeakly(
targetElement: KtElement, targetElement: KtElement,
patternElement: KtElement patternElement: KtElement
): Status { ): Status {
if (!allowWeakMatches) return UNMATCHED if (!allowWeakMatches) return UNMATCHED
@@ -878,10 +886,9 @@ class KotlinPsiUnifier(
return status return status
} }
private fun substitute(parameter: UnifierParameter, targetElement: PsiElement?): Status { private fun substitute(parameter: UnifierParameter, targetElement: PsiElement?): Status =
val existingArgument = substitution[parameter] when (val existingArgument = substitution[parameter]) {
return when { null -> {
existingArgument == null -> {
substitution[parameter] = targetElement as KtElement substitution[parameter] = targetElement as KtElement
MATCHED MATCHED
} }
@@ -893,11 +900,10 @@ class KotlinPsiUnifier(
status status
} }
} }
}
fun doUnify( fun doUnify(
targetElement: PsiElement?, targetElement: PsiElement?,
patternElement: PsiElement? patternElement: PsiElement?
): Status { ): Status {
val targetElementUnwrapped = targetElement?.unwrap() val targetElementUnwrapped = targetElement?.unwrap()
val patternElementUnwrapped = patternElement?.unwrap() val patternElementUnwrapped = patternElement?.unwrap()
@@ -922,8 +928,7 @@ class KotlinPsiUnifier(
if (referencedPatternDeclaration != null && parameter != null) { if (referencedPatternDeclaration != null && parameter != null) {
if (targetElementUnwrapped is KtExpression) { if (targetElementUnwrapped is KtExpression) {
if (!targetElementUnwrapped.checkType(parameter)) return UNMATCHED if (!targetElementUnwrapped.checkType(parameter)) return UNMATCHED
} } else if (targetElementUnwrapped !is KtUserType) return UNMATCHED
else if (targetElementUnwrapped !is KtUserType) return UNMATCHED
return substitute(parameter, targetElementUnwrapped) return substitute(parameter, targetElementUnwrapped)
} }
@@ -958,12 +963,10 @@ class KotlinPsiUnifier(
private val descriptorToParameter = parameters.associateBy { (it.descriptor as? DeclarationDescriptorWithSource)?.source?.getPsi() } private val descriptorToParameter = parameters.associateBy { (it.descriptor as? DeclarationDescriptorWithSource)?.source?.getPsi() }
private fun PsiElement.unwrap(): PsiElement? { private fun PsiElement.unwrap(): PsiElement? = when (this) {
return when (this) { is KtExpression -> KtPsiUtil.deparenthesize(this)
is KtExpression -> KtPsiUtil.deparenthesize(this) is KtStringTemplateEntryWithExpression -> KtPsiUtil.deparenthesize(expression)
is KtStringTemplateEntryWithExpression -> KtPsiUtil.deparenthesize(expression) else -> this
else -> this
}
} }
private fun PsiElement.unquotedText(): String { private fun PsiElement.unquotedText(): String {
@@ -975,8 +978,7 @@ class KotlinPsiUnifier(
return with(Context(target, pattern)) { return with(Context(target, pattern)) {
val status = doUnify(target, pattern) val status = doUnify(target, pattern)
when { when {
substitution.size != descriptorToParameter.size -> substitution.size != descriptorToParameter.size -> Unmatched
Unmatched
status == MATCHED -> { status == MATCHED -> {
val targetRange = targetSubstringInfo?.createExpression()?.toRange() ?: target val targetRange = targetSubstringInfo?.createExpression()?.toRange() ?: target
if (weakMatches.isEmpty()) { if (weakMatches.isEmpty()) {
@@ -985,14 +987,13 @@ class KotlinPsiUnifier(
WeaklyMatched(targetRange, substitution, weakMatches) WeaklyMatched(targetRange, substitution, weakMatches)
} }
} }
else -> else -> Unmatched
Unmatched
} }
} }
} }
fun unify(targetElement: PsiElement?, patternElement: PsiElement?): UnificationResult = 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 fun PsiElement?.matches(e: PsiElement?): Boolean = KotlinPsiUnifier.DEFAULT.unify(this, e).matched
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* 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.
*/ */
@file:JvmName("ScopeUtils") @file:JvmName("ScopeUtils")
@@ -44,13 +33,15 @@ fun LexicalScope.getAllAccessibleVariables(name: Name): Collection<VariableDescr
} }
fun LexicalScope.getAllAccessibleFunctions(name: Name): Collection<FunctionDescriptor> { fun LexicalScope.getAllAccessibleFunctions(name: Name): Collection<FunctionDescriptor> {
return getImplicitReceiversWithInstance().flatMap { it.type.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_IDE) } + return getImplicitReceiversWithInstance().flatMap {
collectFunctions(name, NoLookupLocation.FROM_IDE) it.type.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_IDE)
} + collectFunctions(name, NoLookupLocation.FROM_IDE)
} }
fun LexicalScope.getVariablesFromImplicitReceivers(name: Name): Collection<VariableDescriptor> = getImplicitReceiversWithInstance().flatMap { fun LexicalScope.getVariablesFromImplicitReceivers(name: Name): Collection<VariableDescriptor> =
it.type.memberScope.getContributedVariables(name, NoLookupLocation.FROM_IDE) getImplicitReceiversWithInstance().flatMap {
} it.type.memberScope.getContributedVariables(name, NoLookupLocation.FROM_IDE)
}
fun LexicalScope.getVariableFromImplicitReceivers(name: Name): VariableDescriptor? { fun LexicalScope.getVariableFromImplicitReceivers(name: Name): VariableDescriptor? {
getImplicitReceiversWithInstance().forEach { getImplicitReceiversWithInstance().forEach {
@@ -80,12 +71,12 @@ fun PsiElement.getResolutionScope(bindingContext: BindingContext): LexicalScope?
return null return null
} }
fun PsiElement.getResolutionScope(bindingContext: BindingContext, resolutionFacade: ResolutionFacade/*TODO: get rid of this parameter*/): LexicalScope { fun PsiElement.getResolutionScope(
return getResolutionScope(bindingContext) ?: bindingContext: BindingContext,
when (containingFile) { resolutionFacade: ResolutionFacade/*TODO: get rid of this parameter*/
is KtFile -> resolutionFacade.getFileResolutionScope(containingFile as KtFile) ): LexicalScope = getResolutionScope(bindingContext) ?: when (containingFile) {
else -> error("Not in KtFile") is KtFile -> resolutionFacade.getFileResolutionScope(containingFile as KtFile)
} else -> error("Not in KtFile")
} }
fun KtElement.getResolutionScope(): LexicalScope { fun KtElement.getResolutionScope(): LexicalScope {
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.resolve.lazy 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) { enum class BodyResolveMode(val bindingTraceFilter: BindingTraceFilter, val doControlFlowAnalysis: Boolean) {
// All body statements are analyzed, diagnostics included // All body statements are analyzed, diagnostics included
FULL(BindingTraceFilter.ACCEPT_ALL, doControlFlowAnalysis = true), FULL(BindingTraceFilter.ACCEPT_ALL, doControlFlowAnalysis = true),
// Analyzes only dependent statements, including all declaration statements (difference from PARTIAL_WITH_CFA) // Analyzes only dependent statements, including all declaration statements (difference from PARTIAL_WITH_CFA)
PARTIAL_FOR_COMPLETION(BindingTraceFilter.NO_DIAGNOSTICS, doControlFlowAnalysis = true), PARTIAL_FOR_COMPLETION(BindingTraceFilter.NO_DIAGNOSTICS, doControlFlowAnalysis = true),
// Analyzes only dependent statements, diagnostics included // Analyzes only dependent statements, diagnostics included
PARTIAL_WITH_DIAGNOSTICS(BindingTraceFilter.ACCEPT_ALL, doControlFlowAnalysis = true), PARTIAL_WITH_DIAGNOSTICS(BindingTraceFilter.ACCEPT_ALL, doControlFlowAnalysis = true),
// Analyzes only dependent statements, performs control flow analysis (mostly needed for isUsedAsExpression / AsStatement) // Analyzes only dependent statements, performs control flow analysis (mostly needed for isUsedAsExpression / AsStatement)
PARTIAL_WITH_CFA(BindingTraceFilter.NO_DIAGNOSTICS, doControlFlowAnalysis = true), PARTIAL_WITH_CFA(BindingTraceFilter.NO_DIAGNOSTICS, doControlFlowAnalysis = true),
// Analyzes only dependent statements, including only used declaration statements, does not perform control flow analysis // Analyzes only dependent statements, including only used declaration statements, does not perform control flow analysis
PARTIAL(BindingTraceFilter.NO_DIAGNOSTICS, doControlFlowAnalysis = false) PARTIAL(BindingTraceFilter.NO_DIAGNOSTICS, doControlFlowAnalysis = false)
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.resolve.lazy package org.jetbrains.kotlin.resolve.lazy
@@ -31,9 +20,9 @@ import java.util.*
//TODO: do resolve anonymous object's body //TODO: do resolve anonymous object's body
class PartialBodyResolveFilter( class PartialBodyResolveFilter(
elementsToResolve: Collection<KtElement>, elementsToResolve: Collection<KtElement>,
private val declaration: KtDeclaration, private val declaration: KtDeclaration,
forCompletion: Boolean forCompletion: Boolean
) : StatementFilter() { ) : StatementFilter() {
private val statementMarks = StatementMarks() private val statementMarks = StatementMarks()
@@ -59,8 +48,7 @@ class PartialBodyResolveFilter(
if (name != null) { if (name != null) {
if (declaration is KtNamedFunction) { if (declaration is KtNamedFunction) {
contextNothingFunctionNames.add(name) contextNothingFunctionNames.add(name)
} } else {
else {
contextNothingVariableNames.add(name) contextNothingVariableNames.add(name)
} }
} }
@@ -91,12 +79,11 @@ class PartialBodyResolveFilter(
if (name != null && nameFilter(name)) { if (name != null && nameFilter(name)) {
statementMarks.mark(statement, MarkLevel.NEED_REFERENCE_RESOLVE) statementMarks.mark(statement, MarkLevel.NEED_REFERENCE_RESOLVE)
} }
} } else if (statement is KtDestructuringDeclaration) {
else if (statement is KtDestructuringDeclaration) {
if (statement.entries.any { if (statement.entries.any {
val name = it.name val name = it.name
name != null && nameFilter(name) name != null && nameFilter(name)
}) { }) {
statementMarks.mark(statement, MarkLevel.NEED_REFERENCE_RESOLVE) statementMarks.mark(statement, MarkLevel.NEED_REFERENCE_RESOLVE)
} }
} }
@@ -116,8 +103,8 @@ class PartialBodyResolveFilter(
if (!smartCastPlaces.isEmpty()) { if (!smartCastPlaces.isEmpty()) {
//TODO: do we really need correct resolve for ALL smart cast places? //TODO: do we really need correct resolve for ALL smart cast places?
smartCastPlaces.values smartCastPlaces.values
.flatten() .flatten()
.forEach { statementMarks.mark(it, MarkLevel.NEED_REFERENCE_RESOLVE) } .forEach { statementMarks.mark(it, MarkLevel.NEED_REFERENCE_RESOLVE) }
updateNameFilter() updateNameFilter()
} }
} }
@@ -140,8 +127,8 @@ class PartialBodyResolveFilter(
* Returns map from smart-cast expression names (variable name or qualified variable name) to places. * Returns map from smart-cast expression names (variable name or qualified variable name) to places.
*/ */
private fun potentialSmartCastPlaces( private fun potentialSmartCastPlaces(
statement: KtExpression, statement: KtExpression,
filter: (SmartCastName) -> Boolean = { true } filter: (SmartCastName) -> Boolean = { true }
): Map<SmartCastName, List<KtExpression>> { ): Map<SmartCastName, List<KtExpression>> {
val map = HashMap<SmartCastName, ArrayList<KtExpression>>(0) val map = HashMap<SmartCastName, ArrayList<KtExpression>>(0)
@@ -235,9 +222,9 @@ class PartialBodyResolveFilter(
if (thenBranch != null && elseBranch != null) { if (thenBranch != null && elseBranch != null) {
val thenCasts = potentialSmartCastPlaces(thenBranch, filter) val thenCasts = potentialSmartCastPlaces(thenBranch, filter)
if (!thenCasts.isEmpty()) { if (thenCasts.isNotEmpty()) {
val elseCasts = potentialSmartCastPlaces(elseBranch) { filter(it) && thenCasts.containsKey(it) } val elseCasts = potentialSmartCastPlaces(elseBranch) { filter(it) && thenCasts.containsKey(it) }
if (!elseCasts.isEmpty()) { if (elseCasts.isNotEmpty()) {
for ((name, places) in thenCasts) { for ((name, places) in thenCasts) {
if (elseCasts.containsKey(name)) { // need filtering by cast names in else-branch if (elseCasts.containsKey(name)) { // need filtering by cast names in else-branch
addPlaces(name, places) addPlaces(name, places)
@@ -262,8 +249,7 @@ class PartialBodyResolveFilter(
// we need to enter the body only for "while(true)" // we need to enter the body only for "while(true)"
if (condition.isTrueConstant()) { if (condition.isTrueConstant()) {
expression.acceptChildren(this) expression.acceptChildren(this)
} } else {
else {
condition?.accept(this) condition?.accept(this)
} }
} }
@@ -406,8 +392,7 @@ class PartialBodyResolveFilter(
insideLoopLevel++ insideLoopLevel++
loop.body?.accept(this) loop.body?.accept(this)
insideLoopLevel-- insideLoopLevel--
} } else {
else {
// do not make sense to search exits inside while-loop as not necessary enter it at all // do not make sense to search exits inside while-loop as not necessary enter it at all
condition.accept(this) condition.accept(this)
} }
@@ -451,8 +436,7 @@ class PartialBodyResolveFilter(
if (expression.operationToken == KtTokens.ELVIS) { if (expression.operationToken == KtTokens.ELVIS) {
// do not search exits after "?:" // do not search exits after "?:"
expression.left?.accept(this) expression.left?.accept(this)
} } else {
else {
super.visitBinaryExpression(expression) super.visitBinaryExpression(expression)
} }
} }
@@ -473,8 +457,8 @@ class PartialBodyResolveFilter(
} }
private data class SmartCastName( private data class SmartCastName(
private val receiverName: SmartCastName?, private val receiverName: SmartCastName?,
private val selectorName: String? /* null means "this" (and receiverName should be null */ private val selectorName: String? /* null means "this" (and receiverName should be null */
) { ) {
init { init {
if (selectorName == null) { 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 { fun affectsNames(nameFilter: (String) -> Boolean): Boolean {
if (selectorName == null) return true if (selectorName == null) return true
@@ -533,8 +517,7 @@ class PartialBodyResolveFilter(
if (names == null) return if (names == null) return
if (filter.names == null) { if (filter.names == null) {
names = null names = null
} } else {
else {
names!!.addAll(filter.names!!) names!!.addAll(filter.names!!)
} }
} }
@@ -562,42 +545,38 @@ class PartialBodyResolveFilter(
private fun KtExpression?.isNullLiteral() = this?.node?.elementType == KtNodeTypes.NULL private fun KtExpression?.isNullLiteral() = this?.node?.elementType == KtNodeTypes.NULL
private fun KtExpression?.isTrueConstant() private fun KtExpression?.isTrueConstant() = this != null && node?.elementType == KtNodeTypes.BOOLEAN_CONSTANT && text == "true"
= this != null && node?.elementType == KtNodeTypes.BOOLEAN_CONSTANT && text == "true"
private fun <T : Any> T?.singletonOrEmptySet(): Set<T> = if (this != null) setOf(this) else setOf() private fun <T : Any> T?.singletonOrEmptySet(): Set<T> = if (this != null) setOf(this) else setOf()
//TODO: review logic //TODO: review logic
private fun isValueNeeded(expression: KtExpression): Boolean { private fun isValueNeeded(expression: KtExpression): Boolean = when (val parent = expression.parent) {
val parent = expression.parent is KtBlockExpression -> expression == parent.lastStatement() && isValueNeeded(parent)
return when (parent) {
is KtBlockExpression -> expression == parent.lastStatement() && isValueNeeded(parent)
is KtContainerNode -> { //TODO - not quite correct is KtContainerNode -> { //TODO - not quite correct
val pparent = parent.parent as? KtExpression val pparent = parent.parent as? KtExpression
pparent != null && isValueNeeded(pparent) pparent != null && isValueNeeded(pparent)
}
is KtDeclarationWithBody -> {
if (expression == parent.bodyExpression)
!parent.hasBlockBody() && !parent.hasDeclaredReturnType()
else
true
}
is KtAnonymousInitializer -> false
else -> true
} }
is KtDeclarationWithBody -> {
if (expression == parent.bodyExpression)
!parent.hasBlockBody() && !parent.hasDeclaredReturnType()
else
true
}
is KtAnonymousInitializer -> false
else -> true
} }
private fun KtBlockExpression.lastStatement(): KtExpression? private fun KtBlockExpression.lastStatement(): KtExpression? =
= lastChild?.siblings(forward = false)?.firstIsInstanceOrNull<KtExpression>() lastChild?.siblings(forward = false)?.firstIsInstanceOrNull<KtExpression>()
private fun PsiElement.isStatement() = this is KtExpression && parent is KtBlockExpression private fun PsiElement.isStatement() = this is KtExpression && parent is KtBlockExpression
private fun KtTypeReference?.containsProbablyNothing() private fun KtTypeReference?.containsProbablyNothing() =
= this?.typeElement?.anyDescendantOfType<KtUserType> { it.isProbablyNothing() } ?: false this?.typeElement?.anyDescendantOfType<KtUserType> { it.isProbablyNothing() } ?: false
} }
private inner class StatementMarks { private inner class StatementMarks {
@@ -627,18 +606,16 @@ class PartialBodyResolveFilter(
} }
} }
fun statementMark(statement: KtExpression): MarkLevel fun statementMark(statement: KtExpression): MarkLevel = statementMarks[statement] ?: MarkLevel.NONE
= statementMarks[statement] ?: MarkLevel.NONE
fun allMarkedStatements(): Collection<KtExpression> fun allMarkedStatements(): Collection<KtExpression> = statementMarks.keys
= statementMarks.keys
fun lastMarkedStatement(block: KtBlockExpression, minLevel: MarkLevel): KtExpression? { fun lastMarkedStatement(block: KtBlockExpression, minLevel: MarkLevel): KtExpression? {
val level = blockLevels[block] ?: MarkLevel.NONE val level = blockLevels[block] ?: MarkLevel.NONE
if (level < minLevel) return null // optimization if (level < minLevel) return null // optimization
return block.lastChild.siblings(forward = false) return block.lastChild.siblings(forward = false)
.filterIsInstance<KtExpression>() .filterIsInstance<KtExpression>()
.first { statementMark(it) >= minLevel } .first { statementMark(it) >= minLevel }
} }
} }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.resolve.scopes package org.jetbrains.kotlin.resolve.scopes
@@ -23,20 +12,22 @@ import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
class ExplicitImportsScope(private val descriptors: Collection<DeclarationDescriptor>) : BaseImportingScope(null) { class ExplicitImportsScope(private val descriptors: Collection<DeclarationDescriptor>) : BaseImportingScope(null) {
override fun getContributedClassifier(name: Name, location: LookupLocation) override fun getContributedClassifier(name: Name, location: LookupLocation) =
= descriptors.filter { it.name == name }.firstIsInstanceOrNull<ClassifierDescriptor>() descriptors.filter { it.name == name }.firstIsInstanceOrNull<ClassifierDescriptor>()
override fun getContributedPackage(name: Name) override fun getContributedPackage(name: Name) = descriptors.filter { it.name == name }.firstIsInstanceOrNull<PackageViewDescriptor>()
= descriptors.filter { it.name == name }.firstIsInstanceOrNull<PackageViewDescriptor>()
override fun getContributedVariables(name: Name, location: LookupLocation) override fun getContributedVariables(name: Name, location: LookupLocation) =
= descriptors.filter { it.name == name }.filterIsInstance<VariableDescriptor>() descriptors.filter { it.name == name }.filterIsInstance<VariableDescriptor>()
override fun getContributedFunctions(name: Name, location: LookupLocation) override fun getContributedFunctions(name: Name, location: LookupLocation) =
= descriptors.filter { it.name == name }.filterIsInstance<FunctionDescriptor>() descriptors.filter { it.name == name }.filterIsInstance<FunctionDescriptor>()
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean, changeNamesForAliased: Boolean) override fun getContributedDescriptors(
= descriptors kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
changeNamesForAliased: Boolean
) = descriptors
override fun computeImportedNames() = descriptors.mapTo(hashSetOf()) { it.name } override fun computeImportedNames() = descriptors.mapTo(hashSetOf()) { it.name }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.util package org.jetbrains.kotlin.util
@@ -31,9 +20,9 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeCheckerImpl
import org.jetbrains.kotlin.types.typeUtil.equalTypesOrNulls import org.jetbrains.kotlin.types.typeUtil.equalTypesOrNulls
fun descriptorsEqualWithSubstitution( fun descriptorsEqualWithSubstitution(
descriptor1: DeclarationDescriptor?, descriptor1: DeclarationDescriptor?,
descriptor2: DeclarationDescriptor?, descriptor2: DeclarationDescriptor?,
checkOriginals: Boolean = true checkOriginals: Boolean = true
): Boolean { ): Boolean {
if (descriptor1 == descriptor2) return true if (descriptor1 == descriptor2) return true
if (descriptor1 == null || descriptor2 == null) return false if (descriptor1 == null || descriptor2 == null) return false
@@ -41,14 +30,15 @@ fun descriptorsEqualWithSubstitution(
if (descriptor1 !is CallableDescriptor) return true if (descriptor1 !is CallableDescriptor) return true
descriptor2 as CallableDescriptor 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 { override fun equals(a: TypeConstructor, b: TypeConstructor): Boolean {
val typeParam1 = a.declarationDescriptor as? TypeParameterDescriptor val typeParam1 = a.declarationDescriptor as? TypeParameterDescriptor
val typeParam2 = b.declarationDescriptor as? TypeParameterDescriptor val typeParam2 = b.declarationDescriptor as? TypeParameterDescriptor
if (typeParam1 != null if (typeParam1 != null
&& typeParam2 != null && typeParam2 != null
&& typeParam1.containingDeclaration == descriptor1 && typeParam1.containingDeclaration == descriptor1
&& typeParam2.containingDeclaration == descriptor2) { && typeParam2.containingDeclaration == descriptor2
) {
return typeParam1.index == typeParam2.index return typeParam1.index == typeParam2.index
} }
@@ -68,25 +58,25 @@ fun descriptorsEqualWithSubstitution(
} }
fun ClassDescriptor.findCallableMemberBySignature( fun ClassDescriptor.findCallableMemberBySignature(
signature: CallableMemberDescriptor, signature: CallableMemberDescriptor,
allowOverridabilityConflicts: Boolean = false allowOverridabilityConflicts: Boolean = false
): CallableMemberDescriptor? { ): CallableMemberDescriptor? {
val descriptorKind = if (signature is FunctionDescriptor) DescriptorKindFilter.FUNCTIONS else DescriptorKindFilter.VARIABLES val descriptorKind = if (signature is FunctionDescriptor) DescriptorKindFilter.FUNCTIONS else DescriptorKindFilter.VARIABLES
return defaultType.memberScope return defaultType.memberScope
.getContributedDescriptors(descriptorKind) .getContributedDescriptors(descriptorKind)
.filterIsInstance<CallableMemberDescriptor>() .filterIsInstance<CallableMemberDescriptor>()
.firstOrNull { .firstOrNull {
if (it.containingDeclaration != this) return@firstOrNull false if (it.containingDeclaration != this) return@firstOrNull false
val overridability = OverridingUtil.DEFAULT.isOverridableBy(it as CallableDescriptor, signature, null).result val overridability = OverridingUtil.DEFAULT.isOverridableBy(it as CallableDescriptor, signature, null).result
overridability == OVERRIDABLE || (allowOverridabilityConflicts && overridability == CONFLICT) overridability == OVERRIDABLE || (allowOverridabilityConflicts && overridability == CONFLICT)
} }
} }
fun TypeConstructor.supertypesWithAny(): Collection<KotlinType> { fun TypeConstructor.supertypesWithAny(): Collection<KotlinType> {
val supertypes = supertypes val supertypes = supertypes
val noSuperClass = supertypes val noSuperClass = supertypes.map { it.constructor.declarationDescriptor as? ClassDescriptor }.all {
.map { it.constructor.declarationDescriptor as? ClassDescriptor } it == null || it.kind == ClassKind.INTERFACE
.all { it == null || it.kind == ClassKind.INTERFACE } }
return if (noSuperClass) supertypes + builtIns.anyType else supertypes return if (noSuperClass) supertypes + builtIns.anyType else supertypes
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.types.substitutions 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.descriptors.ClassDescriptor
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
import java.util.LinkedHashMap import java.util.*
fun getTypeSubstitution(baseType: KotlinType, derivedType: KotlinType): LinkedHashMap<TypeConstructor, TypeProjection>? { fun getTypeSubstitution(baseType: KotlinType, derivedType: KotlinType): LinkedHashMap<TypeConstructor, TypeProjection>? {
val substitutedType = TypeCheckingProcedure.findCorrespondingSupertype(derivedType, baseType) ?: return null val substitutedType = TypeCheckingProcedure.findCorrespondingSupertype(derivedType, baseType) ?: return null
@@ -34,8 +23,8 @@ fun getTypeSubstitution(baseType: KotlinType, derivedType: KotlinType): LinkedHa
} }
fun getCallableSubstitution( fun getCallableSubstitution(
baseCallable: CallableDescriptor, baseCallable: CallableDescriptor,
derivedCallable: CallableDescriptor derivedCallable: CallableDescriptor
): MutableMap<TypeConstructor, TypeProjection>? { ): MutableMap<TypeConstructor, TypeProjection>? {
val baseClass = baseCallable.containingDeclaration as? ClassDescriptor ?: return null val baseClass = baseCallable.containingDeclaration as? ClassDescriptor ?: return null
val derivedClass = derivedCallable.containingDeclaration as? ClassDescriptor ?: return null val derivedClass = derivedCallable.containingDeclaration as? ClassDescriptor ?: return null
@@ -49,8 +38,8 @@ fun getCallableSubstitution(
} }
fun getCallableSubstitutor( fun getCallableSubstitutor(
baseCallable: CallableDescriptor, baseCallable: CallableDescriptor,
derivedCallable: CallableDescriptor derivedCallable: CallableDescriptor
): TypeSubstitutor? { ): TypeSubstitutor? {
return getCallableSubstitution(baseCallable, derivedCallable)?.let { TypeSubstitutor.create(it) } return getCallableSubstitution(baseCallable, derivedCallable)?.let { TypeSubstitutor.create(it) }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea package org.jetbrains.kotlin.idea
@@ -107,7 +96,7 @@ class KotlinIconProvider : IconProvider(), DumbAware {
return PlatformIcons.PUBLIC_ICON return PlatformIcons.PUBLIC_ICON
} }
fun PsiElement.getBaseIcon(): Icon? = when(this) { fun PsiElement.getBaseIcon(): Icon? = when (this) {
is KtPackageDirective -> PlatformIcons.PACKAGE_ICON is KtPackageDirective -> PlatformIcons.PACKAGE_ICON
is KtLightClassForFacade -> KotlinIcons.FILE is KtLightClassForFacade -> KotlinIcons.FILE
is KtLightClassForDecompiledDeclaration -> { is KtLightClassForDecompiledDeclaration -> {
@@ -136,8 +125,7 @@ class KotlinIconProvider : IconProvider(), DumbAware {
is KtParameter -> { is KtParameter -> {
if (KtPsiUtil.getClassIfParameterIsProperty(this) != null) { if (KtPsiUtil.getClassIfParameterIsProperty(this) != null) {
if (isMutable) KotlinIcons.FIELD_VAR else KotlinIcons.FIELD_VAL if (isMutable) KotlinIcons.FIELD_VAR else KotlinIcons.FIELD_VAL
} } else
else
KotlinIcons.PARAMETER KotlinIcons.PARAMETER
} }
is KtProperty -> if (isVar) KotlinIcons.FIELD_VAR else KotlinIcons.FIELD_VAL is KtProperty -> if (isVar) KotlinIcons.FIELD_VAR else KotlinIcons.FIELD_VAL
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.caches package org.jetbrains.kotlin.idea.caches
@@ -97,7 +86,8 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
LOG.error( LOG.error(
"A declaration obtained from index has non-matching name:" + "A declaration obtained from index has non-matching name:" +
"\nin index: $name" + "\nin index: $name" +
"\ndeclared: ${fqName.shortName()}($fqName)") "\ndeclared: ${fqName.shortName()}($fqName)"
)
return@Processor true return@Processor true
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2000-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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -47,7 +47,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentMap import java.util.concurrent.ConcurrentMap
class KotlinPackageContentModificationListener(private val project: Project): Disposable { class KotlinPackageContentModificationListener(private val project: Project) : Disposable {
val connection = project.messageBus.connect() val connection = project.messageBus.connect()
init { init {
@@ -63,8 +63,7 @@ class KotlinPackageContentModificationListener(private val project: Project): Di
if (events.size >= FULL_DROP_THRESHOLD) { if (events.size >= FULL_DROP_THRESHOLD) {
service.onTooComplexChange() service.onTooComplexChange()
} else { } else {
events events.asSequence()
.asSequence()
.filter(::isRelevant) .filter(::isRelevant)
.filter { (it.isValid || it !is VFileCreateEvent) && it.file != null } .filter { (it.isValid || it !is VFileCreateEvent) && it.file != null }
.filter { .filter {
@@ -303,7 +302,9 @@ class PerModulePackageCacheService(private val project: Project) : Disposable {
pendingKtFileChanges.processPending { file -> pendingKtFileChanges.processPending { file ->
if (file.virtualFile != null && file.virtualFile !in projectScope) { if (file.virtualFile != null && file.virtualFile !in projectScope) {
LOG.debugIfEnabled(project) { "Skip $file without vFile, or not in scope: ${file.virtualFile?.let { it !in projectScope }}" } LOG.debugIfEnabled(project) {
"Skip $file without vFile, or not in scope: ${file.virtualFile?.let { it !in projectScope }}"
}
return@processPending return@processPending
} }
val nullableModuleInfo = file.getNullableModuleInfo() val nullableModuleInfo = file.getNullableModuleInfo()
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.caches.lightClasses package org.jetbrains.kotlin.idea.caches.lightClasses
@@ -111,7 +100,12 @@ internal object IDELightClassContexts {
"Class descriptor was not found for ${classOrObject.getElementTextWithContext()}" "Class descriptor was not found for ${classOrObject.getElementTextWithContext()}"
} }
ForceResolveUtil.forceResolveAllContents(classDescriptor) ForceResolveUtil.forceResolveAllContents(classDescriptor)
return IDELightClassConstructionContext(bindingContext, resolutionFacade.moduleDescriptor, classOrObject.languageVersionSettings, EXACT) return IDELightClassConstructionContext(
bindingContext,
resolutionFacade.moduleDescriptor,
classOrObject.languageVersionSettings,
EXACT
)
} }
fun contextForLocalClassOrObject(classOrObject: KtClassOrObject): LightClassConstructionContext { fun contextForLocalClassOrObject(classOrObject: KtClassOrObject): LightClassConstructionContext {
@@ -122,12 +116,22 @@ internal object IDELightClassContexts {
if (descriptor == null) { if (descriptor == null) {
LOG.warn("No class descriptor in context for class: " + classOrObject.getElementTextWithContext()) LOG.warn("No class descriptor in context for class: " + classOrObject.getElementTextWithContext())
return IDELightClassConstructionContext(bindingContext, resolutionFacade.moduleDescriptor, classOrObject.languageVersionSettings, EXACT) return IDELightClassConstructionContext(
bindingContext,
resolutionFacade.moduleDescriptor,
classOrObject.languageVersionSettings,
EXACT
)
} }
ForceResolveUtil.forceResolveAllContents(descriptor) ForceResolveUtil.forceResolveAllContents(descriptor)
return IDELightClassConstructionContext(bindingContext, resolutionFacade.moduleDescriptor, classOrObject.languageVersionSettings, EXACT) return IDELightClassConstructionContext(
bindingContext,
resolutionFacade.moduleDescriptor,
classOrObject.languageVersionSettings,
EXACT
)
} }
@@ -135,7 +139,12 @@ internal object IDELightClassContexts {
val resolveSession = files.first().getResolutionFacade().getFrontendService(ResolveSession::class.java) val resolveSession = files.first().getResolutionFacade().getFrontendService(ResolveSession::class.java)
forceResolvePackageDeclarations(files, resolveSession) forceResolvePackageDeclarations(files, resolveSession)
return IDELightClassConstructionContext(resolveSession.bindingContext, resolveSession.moduleDescriptor, files.first().languageVersionSettings, EXACT) return IDELightClassConstructionContext(
resolveSession.bindingContext,
resolveSession.moduleDescriptor,
files.first().languageVersionSettings,
EXACT
)
} }
fun contextForScript(script: KtScript): LightClassConstructionContext { fun contextForScript(script: KtScript): LightClassConstructionContext {
@@ -145,7 +154,12 @@ internal object IDELightClassContexts {
val descriptor = bindingContext[BindingContext.SCRIPT, script] val descriptor = bindingContext[BindingContext.SCRIPT, script]
if (descriptor == null) { if (descriptor == null) {
LOG.warn("No script descriptor in context for script: " + script.getElementTextWithContext()) LOG.warn("No script descriptor in context for script: " + script.getElementTextWithContext())
return IDELightClassConstructionContext(bindingContext, resolutionFacade.moduleDescriptor, script.languageVersionSettings, EXACT) return IDELightClassConstructionContext(
bindingContext,
resolutionFacade.moduleDescriptor,
script.languageVersionSettings,
EXACT
)
} }
ForceResolveUtil.forceResolveAllContents(descriptor) ForceResolveUtil.forceResolveAllContents(descriptor)
@@ -167,7 +181,12 @@ internal object IDELightClassContexts {
ForceResolveUtil.forceResolveAllContents(descriptor) ForceResolveUtil.forceResolveAllContents(descriptor)
return IDELightClassConstructionContext(resolveSession.bindingContext, resolveSession.moduleDescriptor, classOrObject.languageVersionSettings, LIGHT) return IDELightClassConstructionContext(
resolveSession.bindingContext,
resolveSession.moduleDescriptor,
classOrObject.languageVersionSettings,
LIGHT
)
} }
fun lightContextForFacade(files: List<KtFile>): LightClassConstructionContext { fun lightContextForFacade(files: List<KtFile>): LightClassConstructionContext {
@@ -176,7 +195,12 @@ internal object IDELightClassContexts {
forceResolvePackageDeclarations(files, resolveSession) forceResolvePackageDeclarations(files, resolveSession)
return IDELightClassConstructionContext(resolveSession.bindingContext, resolveSession.moduleDescriptor, files.first().languageVersionSettings, LIGHT) return IDELightClassConstructionContext(
resolveSession.bindingContext,
resolveSession.moduleDescriptor,
files.first().languageVersionSettings,
LIGHT
)
} }
private fun isDummyResolveApplicable(classOrObject: KtClassOrObject): Boolean { private fun isDummyResolveApplicable(classOrObject: KtClassOrObject): Boolean {
@@ -384,7 +408,7 @@ internal object IDELightClassContexts {
private val codegenAffectingAnnotations: CodegenAffectingAnnotations, private val codegenAffectingAnnotations: CodegenAffectingAnnotations,
private val callResolver: CallResolver, private val callResolver: CallResolver,
private val languageVersionSettings: LanguageVersionSettings, private val languageVersionSettings: LanguageVersionSettings,
private val dataFlowValueFactory: DataFlowValueFactory,constantExpressionEvaluator: ConstantExpressionEvaluator, private val dataFlowValueFactory: DataFlowValueFactory, constantExpressionEvaluator: ConstantExpressionEvaluator,
storageManager: StorageManager storageManager: StorageManager
) : AnnotationResolverImpl(callResolver, constantExpressionEvaluator, storageManager) { ) : AnnotationResolverImpl(callResolver, constantExpressionEvaluator, storageManager) {
@@ -404,7 +428,7 @@ internal object IDELightClassContexts {
trace: BindingTrace trace: BindingTrace
): OverloadResolutionResults<FunctionDescriptor> { ): OverloadResolutionResults<FunctionDescriptor> {
val annotationConstructor = annotationClassByEntry(annotationEntry)?.constructors?.singleOrNull() val annotationConstructor = annotationClassByEntry(annotationEntry)?.constructors?.singleOrNull()
?: return super.resolveAnnotationCall(annotationEntry, scope, trace) ?: return super.resolveAnnotationCall(annotationEntry, scope, trace)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return callResolver.resolveConstructorCall( return callResolver.resolveConstructorCall(
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.caches.lightClasses package org.jetbrains.kotlin.idea.caches.lightClasses
@@ -108,10 +97,10 @@ private object DummyJavaPsiFactory {
val canonicalText = GenericsUtil.getVariableTypeByExpressionType(returnType).getCanonicalText(true) val canonicalText = GenericsUtil.getVariableTypeByExpressionType(returnType).getCanonicalText(true)
val file = createDummyJavaFile(project, "class _Dummy_ { public $canonicalText $name() {\n} }") val file = createDummyJavaFile(project, "class _Dummy_ { public $canonicalText $name() {\n} }")
val klass = file.classes.singleOrNull() val klass = file.classes.singleOrNull()
?: throw IncorrectOperationException("Class was not created. Method name: $name; return type: $canonicalText") ?: throw IncorrectOperationException("Class was not created. Method name: $name; return type: $canonicalText")
return klass.methods.singleOrNull() return klass.methods.singleOrNull()
?: throw IncorrectOperationException("Method was not created. Method name: $name; return type: $canonicalText") ?: throw IncorrectOperationException("Method was not created. Method name: $name; return type: $canonicalText")
} }
fun createDummyClass(project: Project): PsiClass = PsiElementFactory.SERVICE.getInstance(project).createClass("dummy") fun createDummyClass(project: Project): PsiClass = PsiElementFactory.SERVICE.getInstance(project).createClass("dummy")
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.caches.lightClasses package org.jetbrains.kotlin.idea.caches.lightClasses
@@ -40,8 +29,9 @@ class KtLightClassForDecompiledDeclaration(
override fun getOwnInnerClasses(): List<PsiClass> { override fun getOwnInnerClasses(): List<PsiClass> {
val nestedClasses = kotlinOrigin?.declarations?.filterIsInstance<KtClassOrObject>() ?: emptyList() val nestedClasses = kotlinOrigin?.declarations?.filterIsInstance<KtClassOrObject>() ?: emptyList()
return clsDelegate.ownInnerClasses.map { innerClsClass -> return clsDelegate.ownInnerClasses.map { innerClsClass ->
KtLightClassForDecompiledDeclaration(innerClsClass as ClsClassImpl, KtLightClassForDecompiledDeclaration(
nestedClasses.firstOrNull { innerClsClass.name == it.name }, file innerClsClass as ClsClassImpl,
nestedClasses.firstOrNull { innerClsClass.name == it.name }, file
) )
} }
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2017 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2000-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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -184,6 +184,7 @@ sealed class LazyLightClassDataHolder(
} }
private val PsiMember.debugName private val PsiMember.debugName
get() = "${this::class.java.simpleName}:${this.name} ${this.memberIndex}" + if (this is PsiMethod) " (with ${parameterList.parametersCount} parameters)" else "" get() = "${this::class.java
.simpleName}:${this.name} ${this.memberIndex}" + if (this is PsiMethod) " (with ${parameterList.parametersCount} parameters)" else ""
var KtClassOrObject.hasLightClassMatchingErrors: Boolean by NotNullableUserDataProperty(Key.create("LIGHT_CLASS_MATCHING_ERRORS"), false) var KtClassOrObject.hasLightClassMatchingErrors: Boolean by NotNullableUserDataProperty(Key.create("LIGHT_CLASS_MATCHING_ERRORS"), false)
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2000-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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -233,8 +233,11 @@ fun Module.testSourceInfo(): ModuleTestSourceInfo? = if (hasTestRoots()) ModuleT
internal fun Module.correspondingModuleInfos(): List<ModuleSourceInfo> = listOf(testSourceInfo(), productionSourceInfo()).filterNotNull() internal fun Module.correspondingModuleInfos(): List<ModuleSourceInfo> = listOf(testSourceInfo(), productionSourceInfo()).filterNotNull()
private fun Module.hasProductionRoots() = hasRootsOfType(JavaSourceRootType.SOURCE) || hasRootsOfType(SourceKotlinRootType) || (isNewMPPModule && sourceType == SourceType.PRODUCTION) private fun Module.hasProductionRoots() =
private fun Module.hasTestRoots() = hasRootsOfType(JavaSourceRootType.TEST_SOURCE) || hasRootsOfType(TestSourceKotlinRootType) || (isNewMPPModule && sourceType == SourceType.TEST) hasRootsOfType(JavaSourceRootType.SOURCE) || hasRootsOfType(SourceKotlinRootType) || (isNewMPPModule && sourceType == SourceType.PRODUCTION)
private fun Module.hasTestRoots() =
hasRootsOfType(JavaSourceRootType.TEST_SOURCE) || hasRootsOfType(TestSourceKotlinRootType) || (isNewMPPModule && sourceType == SourceType.TEST)
private fun Module.hasRootsOfType(sourceRootType: JpsModuleSourceRootType<*>): Boolean = private fun Module.hasRootsOfType(sourceRootType: JpsModuleSourceRootType<*>): Boolean =
rootManager.contentEntries.any { it.getSourceFolders(sourceRootType).isNotEmpty() } rootManager.contentEntries.any { it.getSourceFolders(sourceRootType).isNotEmpty() }
@@ -322,7 +325,8 @@ open class LibraryInfo(val project: Project, val library: Library) : IdeaModuleI
override fun hashCode(): Int = 43 * library.hashCode() override fun hashCode(): Int = 43 * library.hashCode()
} }
data class LibrarySourceInfo(val project: Project, val library: Library, override val binariesModuleInfo: BinaryModuleInfo) : IdeaModuleInfo, SourceForBinaryModuleInfo { data class LibrarySourceInfo(val project: Project, val library: Library, override val binariesModuleInfo: BinaryModuleInfo) :
IdeaModuleInfo, SourceForBinaryModuleInfo {
override val name: Name = Name.special("<sources for library ${library.name}>") override val name: Name = Name.special("<sources for library ${library.name}>")
@@ -330,7 +334,8 @@ data class LibrarySourceInfo(val project: Project, val library: Library, overrid
LibrarySourceScope( LibrarySourceScope(
project, project,
library library
), project) ), project
)
override fun modulesWhoseInternalsAreVisible(): Collection<ModuleInfo> { override fun modulesWhoseInternalsAreVisible(): Collection<ModuleInfo> {
return createLibraryInfo(project, library) return createLibraryInfo(project, library)
@@ -101,14 +101,14 @@ private sealed class ModuleInfoCollector<out T>(
LOG.error("Could not find correct module information.\nReason: $reason") LOG.error("Could not find correct module information.\nReason: $reason")
NotUnderContentRootModuleInfo NotUnderContentRootModuleInfo
}, },
virtualFileProcessor = processor@ { project, virtualFile, isLibrarySource -> virtualFileProcessor = processor@{ project, virtualFile, isLibrarySource ->
collectInfosByVirtualFile( collectInfosByVirtualFile(
project, project,
virtualFile, virtualFile,
isLibrarySource, isLibrarySource
{ ) {
return@processor it ?: NotUnderContentRootModuleInfo return@processor it ?: NotUnderContentRootModuleInfo
}) }
} }
) )
@@ -118,12 +118,12 @@ private sealed class ModuleInfoCollector<out T>(
LOG.warn("Could not find correct module information.\nReason: $reason") LOG.warn("Could not find correct module information.\nReason: $reason")
null null
}, },
virtualFileProcessor = processor@ { project, virtualFile, isLibrarySource -> virtualFileProcessor = processor@{ project, virtualFile, isLibrarySource ->
collectInfosByVirtualFile( collectInfosByVirtualFile(
project, project,
virtualFile, virtualFile,
isLibrarySource, isLibrarySource
{ return@processor it }) ) { return@processor it }
} }
) )
@@ -138,8 +138,8 @@ private sealed class ModuleInfoCollector<out T>(
collectInfosByVirtualFile( collectInfosByVirtualFile(
project, project,
virtualFile, virtualFile,
isLibrarySource, isLibrarySource
{ yieldIfNotNull(it) }) ) { yieldIfNotNull(it) }
} }
} }
) )
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2000-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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -103,7 +103,10 @@ val Module.implementedModules: List<Module>
KotlinMultiplatformVersion.M2 -> { KotlinMultiplatformVersion.M2 -> {
rootManager.dependencies.filter { rootManager.dependencies.filter {
// TODO: remove additional android check // TODO: remove additional android check
it.isNewMPPModule && it.platform.isCommon() && it.externalProjectId == externalProjectId && (isAndroidModule() || it.isTestModule == isTestModule) it.isNewMPPModule &&
it.platform.isCommon() &&
it.externalProjectId == externalProjectId &&
(isAndroidModule() || it.isTestModule == isTestModule)
} }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.caches.resolve package org.jetbrains.kotlin.idea.caches.resolve
@@ -224,7 +213,8 @@ internal class PerFileAnalysisCache(val file: KtFile, componentProvider: Compone
} }
} }
private class MergedDiagnostics(val diagnostics: Collection<Diagnostic>, override val modificationTracker: ModificationTracker) : Diagnostics { private class MergedDiagnostics(val diagnostics: Collection<Diagnostic>, override val modificationTracker: ModificationTracker) :
Diagnostics {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private val elementsCache = DiagnosticsElementsCache(this) { true } private val elementsCache = DiagnosticsElementsCache(this) { true }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.caches.resolve package org.jetbrains.kotlin.idea.caches.resolve
@@ -69,8 +58,9 @@ internal class ProjectResolutionFacade(
} }
} }
val allDependencies = val allDependencies = resolverForProjectDependencies + listOf(
resolverForProjectDependencies + listOf(KotlinCodeBlockModificationListener.getInstance(project).kotlinOutOfCodeBlockTracker) KotlinCodeBlockModificationListener.getInstance(project).kotlinOutOfCodeBlockTracker
)
CachedValueProvider.Result.create(results, allDependencies) CachedValueProvider.Result.create(results, allDependencies)
}, false }, false
) )
@@ -114,8 +104,8 @@ internal class ProjectResolutionFacade(
internal fun resolverForElement(element: PsiElement): ResolverForModule { internal fun resolverForElement(element: PsiElement): ResolverForModule {
val infos = element.getModuleInfos() val infos = element.getModuleInfos()
return infos.asIterable().firstNotNullResult { cachedResolverForProject.tryGetResolverForModule(it) } return infos.asIterable().firstNotNullResult { cachedResolverForProject.tryGetResolverForModule(it) }
?: cachedResolverForProject.tryGetResolverForModule(NotUnderContentRootModuleInfo) ?: cachedResolverForProject.tryGetResolverForModule(NotUnderContentRootModuleInfo)
?: cachedResolverForProject.diagnoseUnknownModuleInfo(infos.toList()) ?: cachedResolverForProject.diagnoseUnknownModuleInfo(infos.toList())
} }
internal fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) = internal fun resolverForDescriptor(moduleDescriptor: ModuleDescriptor) =
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * 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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -19,11 +19,11 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
import org.jetbrains.kotlin.idea.caches.project.getNullableModuleInfo import org.jetbrains.kotlin.idea.caches.project.getNullableModuleInfo
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
@@ -205,7 +205,8 @@ private fun StringBuilder.appendElement(element: PsiElement) {
val moduleName = ifIndexReady { ModuleUtil.findModuleForFile(virtualFile, element.project)?.name ?: "null" }?.result val moduleName = ifIndexReady { ModuleUtil.findModuleForFile(virtualFile, element.project)?.name ?: "null" }?.result
info( info(
"ideaModule", "ideaModule",
moduleName ?: "<index not ready>") moduleName ?: "<index not ready>"
)
} }
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2000-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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -34,8 +34,13 @@ fun getResolveScope(file: KtFile): GlobalSearchScope {
} }
return when (file.getModuleInfo()) { return when (file.getModuleInfo()) {
is ModuleSourceInfo -> enlargedSearchScope(KotlinSourceFilterScope.projectSourceAndClassFiles(file.resolveScope, file.project), file) is ModuleSourceInfo -> enlargedSearchScope(
is ScriptModuleInfo -> file.getModuleInfo().dependencies().map { it.contentScope() }.let { GlobalSearchScope.union(it.toTypedArray()) } KotlinSourceFilterScope.projectSourceAndClassFiles(file.resolveScope, file.project),
file
)
is ScriptModuleInfo -> file.getModuleInfo().dependencies().map { it.contentScope() }.let {
GlobalSearchScope.union(it.toTypedArray())
}
else -> GlobalSearchScope.EMPTY_SCOPE else -> GlobalSearchScope.EMPTY_SCOPE
} }
} }
@@ -9,4 +9,5 @@ import com.intellij.psi.impl.PsiModificationTrackerImpl
// BUNCH: 191 // BUNCH: 191
@Suppress("unused") @Suppress("unused")
val PsiModificationTrackerImpl.isEnableLanguageTrackerCompat get() = true val PsiModificationTrackerImpl.isEnableLanguageTrackerCompat
get() = true
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.codeInsight package org.jetbrains.kotlin.idea.codeInsight
@@ -33,9 +22,9 @@ object DescriptorToSourceUtilsIde {
// Returns all PSI elements for descriptor. It can find declarations in builtins or decompiled code. // Returns all PSI elements for descriptor. It can find declarations in builtins or decompiled code.
fun getAllDeclarations( fun getAllDeclarations(
project: Project, project: Project,
targetDescriptor: DeclarationDescriptor, targetDescriptor: DeclarationDescriptor,
builtInsSearchScope: GlobalSearchScope? = null builtInsSearchScope: GlobalSearchScope? = null
): Collection<PsiElement> { ): Collection<PsiElement> {
val result = getDeclarationsStream(project, targetDescriptor, builtInsSearchScope).toHashSet() val result = getDeclarationsStream(project, targetDescriptor, builtInsSearchScope).toHashSet()
// filter out elements which are navigate to some other element of the result // filter out elements which are navigate to some other element of the result
@@ -44,15 +33,15 @@ object DescriptorToSourceUtilsIde {
} }
private fun getDeclarationsStream( private fun getDeclarationsStream(
project: Project, targetDescriptor: DeclarationDescriptor, builtInsSearchScope: GlobalSearchScope? = null project: Project, targetDescriptor: DeclarationDescriptor, builtInsSearchScope: GlobalSearchScope? = null
): Sequence<PsiElement> { ): Sequence<PsiElement> {
val effectiveReferencedDescriptors = DescriptorToSourceUtils.getEffectiveReferencedDescriptors(targetDescriptor).asSequence() val effectiveReferencedDescriptors = DescriptorToSourceUtils.getEffectiveReferencedDescriptors(targetDescriptor).asSequence()
return effectiveReferencedDescriptors.flatMap { effectiveReferenced -> return effectiveReferencedDescriptors.flatMap { effectiveReferenced ->
// References in library sources should be resolved to corresponding decompiled declarations, // References in library sources should be resolved to corresponding decompiled declarations,
// therefore we put both source declaration and decompiled declaration to stream, and afterwards we filter it in getAllDeclarations // therefore we put both source declaration and decompiled declaration to stream, and afterwards we filter it in getAllDeclarations
sequenceOfLazyValues( sequenceOfLazyValues(
{ DescriptorToSourceUtils.getSourceFromDescriptor(effectiveReferenced) }, { DescriptorToSourceUtils.getSourceFromDescriptor(effectiveReferenced) },
{ findDecompiledDeclaration(project, effectiveReferenced, builtInsSearchScope) } { findDecompiledDeclaration(project, effectiveReferenced, builtInsSearchScope) }
) )
}.filterNotNull() }.filterNotNull()
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.compiler.configuration package org.jetbrains.kotlin.idea.compiler.configuration
@@ -32,7 +21,8 @@ import org.jetbrains.kotlin.cli.common.arguments.*
import org.jetbrains.kotlin.idea.syncPublisherWithDisposeCheck import org.jetbrains.kotlin.idea.syncPublisherWithDisposeCheck
import kotlin.reflect.KClass import kotlin.reflect.KClass
abstract class BaseKotlinCompilerSettings<T : Freezable> protected constructor(private val project: Project) : PersistentStateComponent<Element>, Cloneable { abstract class BaseKotlinCompilerSettings<T : Freezable> protected constructor(private val project: Project) :
PersistentStateComponent<Element>, Cloneable {
// Based on com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters // Based on com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters
private object DefaultValuesFilter : SerializationFilterBase() { private object DefaultValuesFilter : SerializationFilterBase() {
private val defaultBeans = THashMap<Class<*>, Any>() private val defaultBeans = THashMap<Class<*>, Any>()
@@ -1,24 +1,14 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.compiler.configuration package org.jetbrains.kotlin.idea.compiler.configuration
import com.intellij.openapi.components.* import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.util.text.VersionComparatorUtil
import org.jdom.Element import org.jdom.Element
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.setApiVersionToLanguageVersionIfNeeded import org.jetbrains.kotlin.cli.common.arguments.setApiVersionToLanguageVersionIfNeeded
@@ -49,6 +39,6 @@ class KotlinCommonCompilerArgumentsHolder(project: Project) : BaseKotlinCompiler
companion object { companion object {
fun getInstance(project: Project) = fun getInstance(project: Project) =
ServiceManager.getService<KotlinCommonCompilerArgumentsHolder>(project, KotlinCommonCompilerArgumentsHolder::class.java)!! ServiceManager.getService<KotlinCommonCompilerArgumentsHolder>(project, KotlinCommonCompilerArgumentsHolder::class.java)!!
} }
} }
@@ -1,22 +1,13 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.compiler.configuration package org.jetbrains.kotlin.idea.compiler.configuration
import com.intellij.openapi.components.* import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.config.CompilerSettings import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.config.SettingConstants import org.jetbrains.kotlin.config.SettingConstants
@@ -27,7 +18,6 @@ class KotlinCompilerSettings(project: Project) : BaseKotlinCompilerSettings<Comp
override fun createSettings() = CompilerSettings() override fun createSettings() = CompilerSettings()
companion object { companion object {
fun getInstance(project: Project) = ServiceManager.getService(project, KotlinCompilerSettings::class.java)!! fun getInstance(project: Project) = ServiceManager.getService(project, KotlinCompilerSettings::class.java)!!
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler package org.jetbrains.kotlin.idea.decompiler
@@ -29,20 +18,19 @@ import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.utils.concurrent.block.LockedClearableLazyValue import org.jetbrains.kotlin.utils.concurrent.block.LockedClearableLazyValue
class KotlinDecompiledFileViewProvider( class KotlinDecompiledFileViewProvider(
manager: PsiManager, manager: PsiManager,
file: VirtualFile, file: VirtualFile,
physical: Boolean, physical: Boolean,
private val factory: (KotlinDecompiledFileViewProvider) -> KtDecompiledFile? private val factory: (KotlinDecompiledFileViewProvider) -> KtDecompiledFile?
) : SingleRootFileViewProvider(manager, file, physical, KotlinLanguage.INSTANCE) { ) : SingleRootFileViewProvider(manager, file, physical, KotlinLanguage.INSTANCE) {
val content : LockedClearableLazyValue<String> = LockedClearableLazyValue(Any()) { val content: LockedClearableLazyValue<String> = LockedClearableLazyValue(Any()) {
val psiFile = createFile(manager.project, file, KotlinFileType.INSTANCE) val psiFile = createFile(manager.project, file, KotlinFileType.INSTANCE)
val text = psiFile?.text ?: "" val text = psiFile?.text ?: ""
DebugUtil.startPsiModification("Invalidating throw-away copy of file that was used for getting text") DebugUtil.startPsiModification("Invalidating throw-away copy of file that was used for getting text")
try { try {
(psiFile as? PsiFileImpl)?.markInvalidated() (psiFile as? PsiFileImpl)?.markInvalidated()
} } finally {
finally {
DebugUtil.finishPsiModification() DebugUtil.finishPsiModification()
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler package org.jetbrains.kotlin.idea.decompiler
@@ -25,8 +14,8 @@ import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.utils.concurrent.block.LockedClearableLazyValue import org.jetbrains.kotlin.utils.concurrent.block.LockedClearableLazyValue
open class KtDecompiledFile( open class KtDecompiledFile(
private val provider: KotlinDecompiledFileViewProvider, private val provider: KotlinDecompiledFileViewProvider,
buildDecompiledText: (VirtualFile) -> DecompiledText buildDecompiledText: (VirtualFile) -> DecompiledText
) : KtFile(provider, true) { ) : KtFile(provider, true) {
private val decompiledText = LockedClearableLazyValue(Any()) { private val decompiledText = LockedClearableLazyValue(Any()) {
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.classFile package org.jetbrains.kotlin.idea.decompiler.classFile
@@ -51,8 +40,8 @@ fun DeserializerForClassfileDecompiler(classFile: VirtualFile): DeserializerForC
} }
class DeserializerForClassfileDecompiler( class DeserializerForClassfileDecompiler(
packageDirectory: VirtualFile, packageDirectory: VirtualFile,
directoryPackageFqName: FqName directoryPackageFqName: FqName
) : DeserializerForDecompilerBase(directoryPackageFqName) { ) : DeserializerForDecompilerBase(directoryPackageFqName) {
override val builtIns: KotlinBuiltIns get() = DefaultBuiltIns.Instance override val builtIns: KotlinBuiltIns get() = DefaultBuiltIns.Instance
@@ -64,7 +53,7 @@ class DeserializerForClassfileDecompiler(
val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG) val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG)
val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor) val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor)
val annotationAndConstantLoader = val annotationAndConstantLoader =
BinaryClassAnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, storageManager, classFinder) BinaryClassAnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, storageManager, classFinder)
val configuration = object : DeserializationConfiguration { val configuration = object : DeserializationConfiguration {
override val readDeserializedContracts: Boolean override val readDeserializedContracts: Boolean
@@ -72,11 +61,11 @@ class DeserializerForClassfileDecompiler(
} }
deserializationComponents = DeserializationComponents( deserializationComponents = DeserializationComponents(
storageManager, moduleDescriptor, configuration, classDataFinder, annotationAndConstantLoader, storageManager, moduleDescriptor, configuration, classDataFinder, annotationAndConstantLoader,
packageFragmentProvider, ResolveEverythingToKotlinAnyLocalClassifierResolver(builtIns), LoggingErrorReporter(LOG), packageFragmentProvider, ResolveEverythingToKotlinAnyLocalClassifierResolver(builtIns), LoggingErrorReporter(LOG),
LookupTracker.DO_NOTHING, JavaFlexibleTypeDeserializer, emptyList(), notFoundClasses, LookupTracker.DO_NOTHING, JavaFlexibleTypeDeserializer, emptyList(), notFoundClasses,
ContractDeserializerImpl(configuration, storageManager), ContractDeserializerImpl(configuration, storageManager),
extensionRegistryLite = JvmProtoBufUtil.EXTENSION_REGISTRY extensionRegistryLite = JvmProtoBufUtil.EXTENSION_REGISTRY
) )
} }
@@ -108,8 +97,8 @@ class DeserializerForClassfileDecompiler(
} }
class DirectoryBasedClassFinder( class DirectoryBasedClassFinder(
val packageDirectory: VirtualFile, val packageDirectory: VirtualFile,
val directoryPackageFqName: FqName val directoryPackageFqName: FqName
) : KotlinClassFinder { ) : KotlinClassFinder {
override fun findKotlinClassOrContent(javaClass: JavaClass) = findKotlinClassOrContent(javaClass.classId!!) override fun findKotlinClassOrContent(javaClass: JavaClass) = findKotlinClassOrContent(javaClass.classId!!)
@@ -136,8 +125,8 @@ class DirectoryBasedClassFinder(
} }
class DirectoryBasedDataFinder( class DirectoryBasedDataFinder(
val classFinder: DirectoryBasedClassFinder, val classFinder: DirectoryBasedClassFinder,
val log: Logger val log: Logger
) : ClassDataFinder { ) : ClassDataFinder {
override fun findClassData(classId: ClassId): ClassData? { override fun findClassData(classId: ClassId): ClassData? {
val binaryClass = classFinder.findKotlinClass(classId) ?: return null val binaryClass = classFinder.findKotlinClass(classId) ?: return null
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.classFile package org.jetbrains.kotlin.idea.decompiler.classFile
@@ -64,8 +53,8 @@ private val decompilerRendererForClassFiles = DescriptorRenderer.withOptions {
} }
fun buildDecompiledTextForClassFile( fun buildDecompiledTextForClassFile(
classFile: VirtualFile, classFile: VirtualFile,
resolver: ResolverForDecompiler = DeserializerForClassfileDecompiler(classFile) resolver: ResolverForDecompiler = DeserializerForClassfileDecompiler(classFile)
): DecompiledText { ): DecompiledText {
val classHeader = val classHeader =
IDEKotlinBinaryClassCache.getInstance().getKotlinBinaryClassHeaderData(classFile) IDEKotlinBinaryClassCache.getInstance().getKotlinBinaryClassHeaderData(classFile)
@@ -77,9 +66,10 @@ fun buildDecompiledTextForClassFile(
return createIncompatibleAbiVersionDecompiledText(JvmMetadataVersion.INSTANCE, classHeader.metadataVersion) return createIncompatibleAbiVersionDecompiledText(JvmMetadataVersion.INSTANCE, classHeader.metadataVersion)
} }
fun buildText(declarations: List<DeclarationDescriptor>) = fun buildText(declarations: List<DeclarationDescriptor>) = buildDecompiledText(
buildDecompiledText(classHeader.packageName?.let(::FqName) ?: classId.packageFqName, classHeader.packageName?.let(::FqName) ?: classId.packageFqName,
declarations, decompilerRendererForClassFiles, listOf(ByDescriptorIndexer, BySignatureIndexer)) declarations, decompilerRendererForClassFiles, listOf(ByDescriptorIndexer, BySignatureIndexer)
)
return when (classHeader.kind) { return when (classHeader.kind) {
KotlinClassHeader.Kind.FILE_FACADE -> KotlinClassHeader.Kind.FILE_FACADE ->
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.classFile package org.jetbrains.kotlin.idea.decompiler.classFile
@@ -103,7 +92,7 @@ open class KotlinClsStubBuilder : ClsStubBuilder() {
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings) val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings)
val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable)) val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable))
val fqName = header.packageName?.let { ClassId(FqName(it), classId.relativeClassName, classId.isLocal).asSingleFqName() } val fqName = header.packageName?.let { ClassId(FqName(it), classId.relativeClassName, classId.isLocal).asSingleFqName() }
?: classId.asSingleFqName() ?: classId.asSingleFqName()
createFileFacadeStub(packageProto, fqName, context) createFileFacadeStub(packageProto, fqName, context)
} }
else -> throw IllegalStateException("Should have processed " + file.path + " with header $header") else -> throw IllegalStateException("Should have processed " + file.path + " with header $header")
@@ -130,9 +119,9 @@ open class KotlinClsStubBuilder : ClsStubBuilder() {
} }
class AnnotationLoaderForClassFileStubBuilder( class AnnotationLoaderForClassFileStubBuilder(
kotlinClassFinder: KotlinClassFinder, kotlinClassFinder: KotlinClassFinder,
private val cachedFile: VirtualFile, private val cachedFile: VirtualFile,
private val cachedFileContent: ByteArray private val cachedFileContent: ByteArray
) : AbstractBinaryClassAnnotationAndConstantLoader<ClassId, Unit>(LockBasedStorageManager.NO_LOCKS, kotlinClassFinder) { ) : AbstractBinaryClassAnnotationAndConstantLoader<ClassId, Unit>(LockBasedStorageManager.NO_LOCKS, kotlinClassFinder) {
override fun getCachedFileContent(kotlinClass: KotlinJvmBinaryClass): ByteArray? { override fun getCachedFileContent(kotlinClass: KotlinJvmBinaryClass): ByteArray? {
@@ -142,15 +131,14 @@ class AnnotationLoaderForClassFileStubBuilder(
return null return null
} }
override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): ClassId = override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): ClassId = nameResolver.getClassId(proto.id)
nameResolver.getClassId(proto.id)
override fun loadConstant(desc: String, initializer: Any) = null override fun loadConstant(desc: String, initializer: Any) = null
override fun transformToUnsignedConstant(constant: Unit) = null override fun transformToUnsignedConstant(constant: Unit) = null
override fun loadAnnotation( override fun loadAnnotation(
annotationClassId: ClassId, source: SourceElement, result: MutableList<ClassId> annotationClassId: ClassId, source: SourceElement, result: MutableList<ClassId>
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? { ): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
result.add(annotationClassId) result.add(annotationClassId)
return null return null
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.common package org.jetbrains.kotlin.idea.decompiler.common
@@ -28,16 +17,16 @@ import org.jetbrains.kotlin.serialization.deserialization.getClassId
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class AnnotationLoaderForStubBuilderImpl( class AnnotationLoaderForStubBuilderImpl(
private val protocol: SerializerExtensionProtocol private val protocol: SerializerExtensionProtocol
) : AnnotationAndConstantLoader<ClassId, Unit> { ) : AnnotationAndConstantLoader<ClassId, Unit> {
override fun loadClassAnnotations(container: ProtoContainer.Class): List<ClassId> = override fun loadClassAnnotations(container: ProtoContainer.Class): List<ClassId> =
container.classProto.getExtension(protocol.classAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) } container.classProto.getExtension(protocol.classAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) }
override fun loadCallableAnnotations( override fun loadCallableAnnotations(
container: ProtoContainer, container: ProtoContainer,
proto: MessageLite, proto: MessageLite,
kind: AnnotatedCallableKind kind: AnnotatedCallableKind
): List<ClassId> { ): List<ClassId> {
val annotations = when (proto) { val annotations = when (proto) {
is ProtoBuf.Constructor -> proto.getExtension(protocol.constructorAnnotation) is ProtoBuf.Constructor -> proto.getExtension(protocol.constructorAnnotation)
@@ -60,35 +49,36 @@ class AnnotationLoaderForStubBuilderImpl(
emptyList() emptyList()
override fun loadEnumEntryAnnotations(container: ProtoContainer, proto: ProtoBuf.EnumEntry): List<ClassId> = override fun loadEnumEntryAnnotations(container: ProtoContainer, proto: ProtoBuf.EnumEntry): List<ClassId> =
proto.getExtension(protocol.enumEntryAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) } proto.getExtension(protocol.enumEntryAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) }
override fun loadValueParameterAnnotations( override fun loadValueParameterAnnotations(
container: ProtoContainer, container: ProtoContainer,
callableProto: MessageLite, callableProto: MessageLite,
kind: AnnotatedCallableKind, kind: AnnotatedCallableKind,
parameterIndex: Int, parameterIndex: Int,
proto: ProtoBuf.ValueParameter proto: ProtoBuf.ValueParameter
): List<ClassId> = ): List<ClassId> =
proto.getExtension(protocol.parameterAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) } proto.getExtension(protocol.parameterAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) }
override fun loadExtensionReceiverParameterAnnotations( override fun loadExtensionReceiverParameterAnnotations(
container: ProtoContainer, container: ProtoContainer,
proto: MessageLite, proto: MessageLite,
kind: AnnotatedCallableKind kind: AnnotatedCallableKind
): List<ClassId> = emptyList() ): List<ClassId> = emptyList()
override fun loadTypeAnnotations( override fun loadTypeAnnotations(
proto: ProtoBuf.Type, proto: ProtoBuf.Type,
nameResolver: NameResolver nameResolver: NameResolver
): List<ClassId> = ): List<ClassId> =
proto.getExtension(protocol.typeAnnotation).orEmpty().map { nameResolver.getClassId(it.id) } proto.getExtension(protocol.typeAnnotation).orEmpty().map { nameResolver.getClassId(it.id) }
override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List<ClassId> = override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List<ClassId> =
proto.getExtension(protocol.typeParameterAnnotation).orEmpty().map { nameResolver.getClassId(it.id) } proto.getExtension(protocol.typeParameterAnnotation).orEmpty().map { nameResolver.getClassId(it.id) }
override fun loadPropertyConstant( override fun loadPropertyConstant(
container: ProtoContainer, container: ProtoContainer,
proto: ProtoBuf.Property, proto: ProtoBuf.Property,
expectedType: KotlinType expectedType: KotlinType
) {} ) {
}
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.common package org.jetbrains.kotlin.idea.decompiler.common
@@ -101,8 +90,8 @@ abstract class KotlinMetadataDecompiler<out V : BinaryVersion>(
is FileWithMetadata.Compatible -> { is FileWithMetadata.Compatible -> {
val packageFqName = file.packageFqName val packageFqName = file.packageFqName
val resolver = KotlinMetadataDeserializerForDecompiler( val resolver = KotlinMetadataDeserializerForDecompiler(
packageFqName, file.proto, file.nameResolver, file.version, packageFqName, file.proto, file.nameResolver, file.version,
serializerProtocol(), flexibleTypeDeserializer serializerProtocol(), flexibleTypeDeserializer
) )
val declarations = arrayListOf<DeclarationDescriptor>() val declarations = arrayListOf<DeclarationDescriptor>()
declarations.addAll(resolver.resolveDeclarationsInFacade(packageFqName)) declarations.addAll(resolver.resolveDeclarationsInFacade(packageFqName))
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.common package org.jetbrains.kotlin.idea.decompiler.common
@@ -34,12 +23,12 @@ import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
class KotlinMetadataDeserializerForDecompiler( class KotlinMetadataDeserializerForDecompiler(
packageFqName: FqName, packageFqName: FqName,
private val proto: ProtoBuf.PackageFragment, private val proto: ProtoBuf.PackageFragment,
private val nameResolver: NameResolver, private val nameResolver: NameResolver,
private val metadataVersion: BinaryVersion, private val metadataVersion: BinaryVersion,
serializerProtocol: SerializerExtensionProtocol, serializerProtocol: SerializerExtensionProtocol,
flexibleTypeDeserializer: FlexibleTypeDeserializer flexibleTypeDeserializer: FlexibleTypeDeserializer
) : DeserializerForDecompilerBase(packageFqName) { ) : DeserializerForDecompilerBase(packageFqName) {
override val builtIns: KotlinBuiltIns get() = DefaultBuiltIns.Instance override val builtIns: KotlinBuiltIns get() = DefaultBuiltIns.Instance
@@ -49,13 +38,13 @@ class KotlinMetadataDeserializerForDecompiler(
val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor) val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor)
deserializationComponents = DeserializationComponents( deserializationComponents = DeserializationComponents(
storageManager, moduleDescriptor, DeserializationConfiguration.Default, storageManager, moduleDescriptor, DeserializationConfiguration.Default,
ProtoBasedClassDataFinder(proto, nameResolver, metadataVersion), ProtoBasedClassDataFinder(proto, nameResolver, metadataVersion),
AnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, serializerProtocol), packageFragmentProvider, AnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, serializerProtocol), packageFragmentProvider,
ResolveEverythingToKotlinAnyLocalClassifierResolver(builtIns), LoggingErrorReporter(LOG), ResolveEverythingToKotlinAnyLocalClassifierResolver(builtIns), LoggingErrorReporter(LOG),
LookupTracker.DO_NOTHING, flexibleTypeDeserializer, emptyList(), notFoundClasses, LookupTracker.DO_NOTHING, flexibleTypeDeserializer, emptyList(), notFoundClasses,
ContractDeserializer.DEFAULT, ContractDeserializer.DEFAULT,
extensionRegistryLite = serializerProtocol.extensionRegistry extensionRegistryLite = serializerProtocol.extensionRegistry
) )
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.common package org.jetbrains.kotlin.idea.decompiler.common
@@ -30,10 +19,10 @@ import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
import org.jetbrains.kotlin.serialization.deserialization.getClassId import org.jetbrains.kotlin.serialization.deserialization.getClassId
open class KotlinMetadataStubBuilder( open class KotlinMetadataStubBuilder(
private val version: Int, private val version: Int,
private val fileType: FileType, private val fileType: FileType,
private val serializerProtocol: () -> SerializerExtensionProtocol, private val serializerProtocol: () -> SerializerExtensionProtocol,
private val readFile: (VirtualFile, ByteArray) -> FileWithMetadata? private val readFile: (VirtualFile, ByteArray) -> FileWithMetadata?
) : ClsStubBuilder() { ) : ClsStubBuilder() {
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + version override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + version
@@ -51,21 +40,21 @@ open class KotlinMetadataStubBuilder(
val packageFqName = file.packageFqName val packageFqName = file.packageFqName
val nameResolver = file.nameResolver val nameResolver = file.nameResolver
val components = ClsStubBuilderComponents( val components = ClsStubBuilderComponents(
ProtoBasedClassDataFinder(file.proto, nameResolver, file.version), ProtoBasedClassDataFinder(file.proto, nameResolver, file.version),
AnnotationLoaderForStubBuilderImpl(serializerProtocol()), AnnotationLoaderForStubBuilderImpl(serializerProtocol()),
virtualFile virtualFile
) )
val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable)) val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable))
val fileStub = createFileStub(packageFqName, isScript = false) val fileStub = createFileStub(packageFqName, isScript = false)
createDeclarationsStubs( createDeclarationsStubs(
fileStub, context, fileStub, context,
ProtoContainer.Package(packageFqName, context.nameResolver, context.typeTable, source = null), ProtoContainer.Package(packageFqName, context.nameResolver, context.typeTable, source = null),
packageProto packageProto
) )
for (classProto in file.classesToDecompile) { for (classProto in file.classesToDecompile) {
createClassStub( createClassStub(
fileStub, classProto, nameResolver, nameResolver.getClassId(classProto.fqName), source = null, context = context fileStub, classProto, nameResolver, nameResolver.getClassId(classProto.fqName), source = null, context = context
) )
} }
return fileStub return fileStub
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.common package org.jetbrains.kotlin.idea.decompiler.common
@@ -20,21 +9,19 @@ import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledText
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledTextIndex import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledTextIndex
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
private val FILE_ABI_VERSION_MARKER: String = "FILE_ABI" private const val FILE_ABI_VERSION_MARKER: String = "FILE_ABI"
private val CURRENT_ABI_VERSION_MARKER: String = "CURRENT_ABI" private const val CURRENT_ABI_VERSION_MARKER: String = "CURRENT_ABI"
val INCOMPATIBLE_ABI_VERSION_GENERAL_COMMENT: String = "// This class file was compiled with different version of Kotlin compiler and can't be decompiled." val INCOMPATIBLE_ABI_VERSION_GENERAL_COMMENT: String =
private val INCOMPATIBLE_ABI_VERSION_COMMENT: String = "// This class file was compiled with different version of Kotlin compiler and can't be decompiled."
"$INCOMPATIBLE_ABI_VERSION_GENERAL_COMMENT\n" +
private val INCOMPATIBLE_ABI_VERSION_COMMENT: String = "$INCOMPATIBLE_ABI_VERSION_GENERAL_COMMENT\n" +
"//\n" + "//\n" +
"// Current compiler ABI version is $CURRENT_ABI_VERSION_MARKER\n" + "// Current compiler ABI version is $CURRENT_ABI_VERSION_MARKER\n" +
"// File ABI version is $FILE_ABI_VERSION_MARKER" "// File ABI version is $FILE_ABI_VERSION_MARKER"
fun <V : BinaryVersion> createIncompatibleAbiVersionDecompiledText(expectedVersion: V, actualVersion: V): DecompiledText { fun <V : BinaryVersion> createIncompatibleAbiVersionDecompiledText(expectedVersion: V, actualVersion: V): DecompiledText = DecompiledText(
return DecompiledText( INCOMPATIBLE_ABI_VERSION_COMMENT.replace(CURRENT_ABI_VERSION_MARKER, expectedVersion.toString())
INCOMPATIBLE_ABI_VERSION_COMMENT .replace(FILE_ABI_VERSION_MARKER, actualVersion.toString()),
.replace(CURRENT_ABI_VERSION_MARKER, expectedVersion.toString()) DecompiledTextIndex.Empty
.replace(FILE_ABI_VERSION_MARKER, actualVersion.toString()), )
DecompiledTextIndex.Empty
)
}
@@ -1,29 +1,15 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.navigation package org.jetbrains.kotlin.idea.decompiler.navigation
import org.jetbrains.kotlin.psi.KotlinDeclarationNavigationPolicy import org.jetbrains.kotlin.psi.KotlinDeclarationNavigationPolicy
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import com.intellij.openapi.project.DumbService
class KotlinDeclarationNavigationPolicyImpl : KotlinDeclarationNavigationPolicy { class KotlinDeclarationNavigationPolicyImpl : KotlinDeclarationNavigationPolicy {
override fun getOriginalElement(declaration: KtDeclaration) = override fun getOriginalElement(declaration: KtDeclaration) = SourceNavigationHelper.getOriginalElement(declaration)
SourceNavigationHelper.getOriginalElement(declaration)
override fun getNavigationElement(declaration: KtDeclaration) = override fun getNavigationElement(declaration: KtDeclaration) = SourceNavigationHelper.getNavigationElement(declaration)
SourceNavigationHelper.getNavigationElement(declaration)
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.navigation package org.jetbrains.kotlin.idea.decompiler.navigation
@@ -46,10 +35,10 @@ import org.jetbrains.kotlin.types.ErrorUtils
import java.util.* import java.util.*
fun findDecompiledDeclaration( fun findDecompiledDeclaration(
project: Project, project: Project,
referencedDescriptor: DeclarationDescriptor, referencedDescriptor: DeclarationDescriptor,
// TODO: should not require explicitly specified scope to search for builtIns, use SourceElement to provide such information // TODO: should not require explicitly specified scope to search for builtIns, use SourceElement to provide such information
builtInsSearchScope: GlobalSearchScope? builtInsSearchScope: GlobalSearchScope?
): KtDeclaration? { ): KtDeclaration? {
if (ErrorUtils.isError(referencedDescriptor)) return null if (ErrorUtils.isError(referencedDescriptor)) return null
if (isLocal(referencedDescriptor)) return null if (isLocal(referencedDescriptor)) return null
@@ -63,9 +52,9 @@ fun findDecompiledDeclaration(
if (KotlinBuiltIns.isBuiltIn(referencedDescriptor)) { if (KotlinBuiltIns.isBuiltIn(referencedDescriptor)) {
// builtin module does not contain information about it's origin // builtin module does not contain information about it's origin
return builtInsSearchScope?.let { findInScope(referencedDescriptor, it) } return builtInsSearchScope?.let { findInScope(referencedDescriptor, it) }
// fallback on searching everywhere since builtIns are accessible from any context // fallback on searching everywhere since builtIns are accessible from any context
?: findInScope(referencedDescriptor, GlobalSearchScope.allScope(project)) ?: findInScope(referencedDescriptor, GlobalSearchScope.allScope(project))
?: findInScope(referencedDescriptor, EverythingGlobalScope(project)) ?: findInScope(referencedDescriptor, EverythingGlobalScope(project))
} }
return null return null
} }
@@ -73,31 +62,27 @@ fun findDecompiledDeclaration(
private fun findInScope(referencedDescriptor: DeclarationDescriptor, scope: GlobalSearchScope): KtDeclaration? { private fun findInScope(referencedDescriptor: DeclarationDescriptor, scope: GlobalSearchScope): KtDeclaration? {
val project = scope.project ?: return null val project = scope.project ?: return null
val decompiledFiles = findCandidateDeclarationsInIndex( val decompiledFiles = findCandidateDeclarationsInIndex(
referencedDescriptor, KotlinSourceFilterScope.libraryClassFiles(scope, project), project referencedDescriptor, KotlinSourceFilterScope.libraryClassFiles(scope, project), project
).mapNotNullTo(LinkedHashSet()) { ).mapNotNullTo(LinkedHashSet()) {
it?.containingFile as? KtDecompiledFile it?.containingFile as? KtDecompiledFile
} }
return decompiledFiles.asSequence().mapNotNull { return decompiledFiles.asSequence().mapNotNull { file ->
file ->
ByDescriptorIndexer.getDeclarationForDescriptor(referencedDescriptor, file) ByDescriptorIndexer.getDeclarationForDescriptor(referencedDescriptor, file)
}.firstOrNull() }.firstOrNull()
} }
private fun isLocal(descriptor: DeclarationDescriptor): Boolean { private fun isLocal(descriptor: DeclarationDescriptor): Boolean = if (descriptor is ParameterDescriptor) {
return if (descriptor is ParameterDescriptor) { isLocal(descriptor.containingDeclaration)
isLocal(descriptor.containingDeclaration) } else {
} DescriptorUtils.isLocal(descriptor)
else {
DescriptorUtils.isLocal(descriptor)
}
} }
private fun findCandidateDeclarationsInIndex( private fun findCandidateDeclarationsInIndex(
referencedDescriptor: DeclarationDescriptor, referencedDescriptor: DeclarationDescriptor,
scope: GlobalSearchScope, scope: GlobalSearchScope,
project: Project project: Project
): Collection<KtDeclaration?> { ): Collection<KtDeclaration?> {
val containingClass = DescriptorUtils.getParentOfType(referencedDescriptor, ClassDescriptor::class.java, false) val containingClass = DescriptorUtils.getParentOfType(referencedDescriptor, ClassDescriptor::class.java, false)
if (containingClass != null) { if (containingClass != null) {
@@ -105,7 +90,7 @@ private fun findCandidateDeclarationsInIndex(
} }
val topLevelDeclaration = val topLevelDeclaration =
DescriptorUtils.getParentOfType(referencedDescriptor, PropertyDescriptor::class.java, false) as DeclarationDescriptor? DescriptorUtils.getParentOfType(referencedDescriptor, PropertyDescriptor::class.java, false) as DeclarationDescriptor?
?: DescriptorUtils.getParentOfType(referencedDescriptor, TypeAliasConstructorDescriptor::class.java, false)?.typeAliasDescriptor ?: DescriptorUtils.getParentOfType(referencedDescriptor, TypeAliasConstructorDescriptor::class.java, false)?.typeAliasDescriptor
?: DescriptorUtils.getParentOfType(referencedDescriptor, FunctionDescriptor::class.java, false) ?: DescriptorUtils.getParentOfType(referencedDescriptor, FunctionDescriptor::class.java, false)
?: DescriptorUtils.getParentOfType(referencedDescriptor, TypeAliasDescriptor::class.java, false) ?: DescriptorUtils.getParentOfType(referencedDescriptor, TypeAliasDescriptor::class.java, false)
@@ -143,8 +128,10 @@ object ByDescriptorIndexer : DecompiledTextIndexer<String> {
val callable = original.containingDeclaration val callable = original.containingDeclaration
val callableDeclaration = getDeclarationForDescriptor(callable, file) as? KtCallableDeclaration ?: return null val callableDeclaration = getDeclarationForDescriptor(callable, file) as? KtCallableDeclaration ?: return null
if (original.index >= callableDeclaration.valueParameters.size) { if (original.index >= callableDeclaration.valueParameters.size) {
LOG.error("Parameter count mismatch for ${DescriptorRenderer.DEBUG_TEXT.render(callable)}[${original.index}] vs " + LOG.error(
callableDeclaration.valueParameterList?.text) "Parameter count mismatch for ${DescriptorRenderer.DEBUG_TEXT.render(callable)}[${original.index}] vs " +
callableDeclaration.valueParameterList?.text
)
return null return null
} }
return callableDeclaration.valueParameters[original.index] return callableDeclaration.valueParameters[original.index]
@@ -158,8 +145,12 @@ object ByDescriptorIndexer : DecompiledTextIndexer<String> {
val descriptorKey = original.toStringKey() val descriptorKey = original.toStringKey()
if (!file.isContentsLoaded && original is MemberDescriptor) { if (!file.isContentsLoaded && original is MemberDescriptor) {
val hasDeclarationByKey = file.hasDeclarationWithKey(this, descriptorKey) || val hasDeclarationByKey = file.hasDeclarationWithKey(this, descriptorKey) || (getBuiltinsDescriptorKey(descriptor)?.let {
(getBuiltinsDescriptorKey(descriptor)?.let { file.hasDeclarationWithKey(this, it) } ?: false) file.hasDeclarationWithKey(
this,
it
)
} ?: false)
if (hasDeclarationByKey) { if (hasDeclarationByKey) {
val declarationContainer: KtDeclarationContainer? = when { val declarationContainer: KtDeclarationContainer? = when {
DescriptorUtils.isTopLevelDeclaration(original) -> file DescriptorUtils.isTopLevelDeclaration(original) -> file
@@ -190,7 +181,7 @@ object ByDescriptorIndexer : DecompiledTextIndexer<String> {
if (!JvmBuiltInsSettings.isSerializableInJava(classFqName)) return null if (!JvmBuiltInsSettings.isSerializableInJava(classFqName)) return null
val builtInDescriptor = val builtInDescriptor =
DefaultBuiltIns.Instance.builtInsModule.resolveTopLevelClass(classFqName.toSafe(), NoLookupLocation.FROM_IDE) DefaultBuiltIns.Instance.builtInsModule.resolveTopLevelClass(classFqName.toSafe(), NoLookupLocation.FROM_IDE)
return builtInDescriptor?.toStringKey() return builtInDescriptor?.toStringKey()
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.stubBuilder package org.jetbrains.kotlin.idea.decompiler.stubBuilder
@@ -38,22 +27,23 @@ import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
import org.jetbrains.kotlin.serialization.deserialization.getName import org.jetbrains.kotlin.serialization.deserialization.getName
fun createDeclarationsStubs( fun createDeclarationsStubs(
parentStub: StubElement<out PsiElement>, parentStub: StubElement<out PsiElement>,
outerContext: ClsStubBuilderContext, outerContext: ClsStubBuilderContext,
protoContainer: ProtoContainer, protoContainer: ProtoContainer,
packageProto: ProtoBuf.Package packageProto: ProtoBuf.Package
) { ) {
createDeclarationsStubs( createDeclarationsStubs(
parentStub, outerContext, protoContainer, packageProto.functionList, packageProto.propertyList, packageProto.typeAliasList) parentStub, outerContext, protoContainer, packageProto.functionList, packageProto.propertyList, packageProto.typeAliasList
)
} }
fun createDeclarationsStubs( fun createDeclarationsStubs(
parentStub: StubElement<out PsiElement>, parentStub: StubElement<out PsiElement>,
outerContext: ClsStubBuilderContext, outerContext: ClsStubBuilderContext,
protoContainer: ProtoContainer, protoContainer: ProtoContainer,
functionProtos: List<ProtoBuf.Function>, functionProtos: List<ProtoBuf.Function>,
propertyProtos: List<ProtoBuf.Property>, propertyProtos: List<ProtoBuf.Property>,
typeAliasesProtos: List<ProtoBuf.TypeAlias> typeAliasesProtos: List<ProtoBuf.TypeAlias>
) { ) {
for (propertyProto in propertyProtos) { for (propertyProto in propertyProtos) {
if (!shouldSkip(propertyProto.flags, outerContext.nameResolver.getName(propertyProto.name))) { if (!shouldSkip(propertyProto.flags, outerContext.nameResolver.getName(propertyProto.name))) {
@@ -72,10 +62,10 @@ fun createDeclarationsStubs(
} }
fun createConstructorStub( fun createConstructorStub(
parentStub: StubElement<out PsiElement>, parentStub: StubElement<out PsiElement>,
constructorProto: ProtoBuf.Constructor, constructorProto: ProtoBuf.Constructor,
outerContext: ClsStubBuilderContext, outerContext: ClsStubBuilderContext,
protoContainer: ProtoContainer protoContainer: ProtoContainer
) { ) {
ConstructorClsStubBuilder(parentStub, outerContext, protoContainer, constructorProto).build() ConstructorClsStubBuilder(parentStub, outerContext, protoContainer, constructorProto).build()
} }
@@ -90,10 +80,10 @@ private fun shouldSkip(flags: Int, name: Name): Boolean {
} }
abstract class CallableClsStubBuilder( abstract class CallableClsStubBuilder(
parent: StubElement<out PsiElement>, parent: StubElement<out PsiElement>,
outerContext: ClsStubBuilderContext, outerContext: ClsStubBuilderContext,
protected val protoContainer: ProtoContainer, protected val protoContainer: ProtoContainer,
private val typeParameters: List<ProtoBuf.TypeParameter> private val typeParameters: List<ProtoBuf.TypeParameter>
) { ) {
protected val c = outerContext.child(typeParameters) protected val c = outerContext.child(typeParameters)
protected val typeStubBuilder = TypeClsStubBuilder(c) protected val typeStubBuilder = TypeClsStubBuilder(c)
@@ -134,10 +124,10 @@ abstract class CallableClsStubBuilder(
} }
private class FunctionClsStubBuilder( private class FunctionClsStubBuilder(
parent: StubElement<out PsiElement>, parent: StubElement<out PsiElement>,
outerContext: ClsStubBuilderContext, outerContext: ClsStubBuilderContext,
protoContainer: ProtoContainer, protoContainer: ProtoContainer,
private val functionProto: ProtoBuf.Function private val functionProto: ProtoBuf.Function
) : CallableClsStubBuilder(parent, outerContext, protoContainer, functionProto.typeParameterList) { ) : CallableClsStubBuilder(parent, outerContext, protoContainer, functionProto.typeParameterList) {
override val receiverType: ProtoBuf.Type? override val receiverType: ProtoBuf.Type?
get() = functionProto.receiverType(c.typeTable) get() = functionProto.receiverType(c.typeTable)
@@ -145,8 +135,8 @@ private class FunctionClsStubBuilder(
override val receiverAnnotations: List<ClassIdWithTarget> override val receiverAnnotations: List<ClassIdWithTarget>
get() { get() {
return c.components.annotationLoader return c.components.annotationLoader
.loadExtensionReceiverParameterAnnotations(protoContainer, functionProto, AnnotatedCallableKind.FUNCTION) .loadExtensionReceiverParameterAnnotations(protoContainer, functionProto, AnnotatedCallableKind.FUNCTION)
.map { ClassIdWithTarget(it, AnnotationUseSiteTarget.RECEIVER) } .map { ClassIdWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
} }
override val returnType: ProtoBuf.Type? override val returnType: ProtoBuf.Type?
@@ -159,12 +149,12 @@ private class FunctionClsStubBuilder(
override fun createModifierListStub() { override fun createModifierListStub() {
val modalityModifier = if (isTopLevel) listOf() else listOf(MODALITY) val modalityModifier = if (isTopLevel) listOf() else listOf(MODALITY)
val modifierListStubImpl = createModifierListStubForDeclaration( val modifierListStubImpl = createModifierListStubForDeclaration(
callableStub, functionProto.flags, callableStub, functionProto.flags,
listOf(VISIBILITY, OPERATOR, INFIX, EXTERNAL_FUN, INLINE, TAILREC, SUSPEND) + modalityModifier listOf(VISIBILITY, OPERATOR, INFIX, EXTERNAL_FUN, INLINE, TAILREC, SUSPEND) + modalityModifier
) )
val annotationIds = c.components.annotationLoader.loadCallableAnnotations( val annotationIds = c.components.annotationLoader.loadCallableAnnotations(
protoContainer, functionProto, AnnotatedCallableKind.FUNCTION protoContainer, functionProto, AnnotatedCallableKind.FUNCTION
) )
createAnnotationStubs(annotationIds, modifierListStubImpl) createAnnotationStubs(annotationIds, modifierListStubImpl)
} }
@@ -173,24 +163,24 @@ private class FunctionClsStubBuilder(
val callableName = c.nameResolver.getName(functionProto.name) val callableName = c.nameResolver.getName(functionProto.name)
return KotlinFunctionStubImpl( return KotlinFunctionStubImpl(
parent, parent,
callableName.ref(), callableName.ref(),
isTopLevel, isTopLevel,
c.containerFqName.child(callableName), c.containerFqName.child(callableName),
isExtension = functionProto.hasReceiver(), isExtension = functionProto.hasReceiver(),
hasBlockBody = true, hasBlockBody = true,
hasBody = Flags.MODALITY.get(functionProto.flags) != Modality.ABSTRACT, hasBody = Flags.MODALITY.get(functionProto.flags) != Modality.ABSTRACT,
hasTypeParameterListBeforeFunctionName = functionProto.typeParameterList.isNotEmpty(), hasTypeParameterListBeforeFunctionName = functionProto.typeParameterList.isNotEmpty(),
mayHaveContract = functionProto.hasContract() mayHaveContract = functionProto.hasContract()
) )
} }
} }
private class PropertyClsStubBuilder( private class PropertyClsStubBuilder(
parent: StubElement<out PsiElement>, parent: StubElement<out PsiElement>,
outerContext: ClsStubBuilderContext, outerContext: ClsStubBuilderContext,
protoContainer: ProtoContainer, protoContainer: ProtoContainer,
private val propertyProto: ProtoBuf.Property private val propertyProto: ProtoBuf.Property
) : CallableClsStubBuilder(parent, outerContext, protoContainer, propertyProto.typeParameterList) { ) : CallableClsStubBuilder(parent, outerContext, protoContainer, propertyProto.typeParameterList) {
private val isVar = Flags.IS_VAR.get(propertyProto.flags) private val isVar = Flags.IS_VAR.get(propertyProto.flags)
@@ -198,11 +188,9 @@ private class PropertyClsStubBuilder(
get() = propertyProto.receiverType(c.typeTable) get() = propertyProto.receiverType(c.typeTable)
override val receiverAnnotations: List<ClassIdWithTarget> override val receiverAnnotations: List<ClassIdWithTarget>
get() { get() = c.components.annotationLoader
return c.components.annotationLoader .loadExtensionReceiverParameterAnnotations(protoContainer, propertyProto, AnnotatedCallableKind.PROPERTY_GETTER)
.loadExtensionReceiverParameterAnnotations(protoContainer, propertyProto, AnnotatedCallableKind.PROPERTY_GETTER) .map { ClassIdWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
.map { ClassIdWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
}
override val returnType: ProtoBuf.Type? override val returnType: ProtoBuf.Type?
get() = propertyProto.returnType(c.typeTable) get() = propertyProto.returnType(c.typeTable)
@@ -215,8 +203,8 @@ private class PropertyClsStubBuilder(
val modalityModifier = if (isTopLevel) listOf() else listOf(MODALITY) val modalityModifier = if (isTopLevel) listOf() else listOf(MODALITY)
val modifierListStubImpl = createModifierListStubForDeclaration( val modifierListStubImpl = createModifierListStubForDeclaration(
callableStub, propertyProto.flags, callableStub, propertyProto.flags,
listOf(VISIBILITY, LATEINIT, EXTERNAL_PROPERTY) + constModifier + modalityModifier listOf(VISIBILITY, LATEINIT, EXTERNAL_PROPERTY) + constModifier + modalityModifier
) )
val propertyAnnotations = val propertyAnnotations =
@@ -236,25 +224,25 @@ private class PropertyClsStubBuilder(
val callableName = c.nameResolver.getName(propertyProto.name) val callableName = c.nameResolver.getName(propertyProto.name)
return KotlinPropertyStubImpl( return KotlinPropertyStubImpl(
parent, parent,
callableName.ref(), callableName.ref(),
isVar, isVar,
isTopLevel, isTopLevel,
hasDelegate = false, hasDelegate = false,
hasDelegateExpression = false, hasDelegateExpression = false,
hasInitializer = false, hasInitializer = false,
isExtension = propertyProto.hasReceiver(), isExtension = propertyProto.hasReceiver(),
hasReturnTypeRef = true, hasReturnTypeRef = true,
fqName = c.containerFqName.child(callableName) fqName = c.containerFqName.child(callableName)
) )
} }
} }
private class ConstructorClsStubBuilder( private class ConstructorClsStubBuilder(
parent: StubElement<out PsiElement>, parent: StubElement<out PsiElement>,
outerContext: ClsStubBuilderContext, outerContext: ClsStubBuilderContext,
protoContainer: ProtoContainer, protoContainer: ProtoContainer,
private val constructorProto: ProtoBuf.Constructor private val constructorProto: ProtoBuf.Constructor
) : CallableClsStubBuilder(parent, outerContext, protoContainer, emptyList()) { ) : CallableClsStubBuilder(parent, outerContext, protoContainer, emptyList()) {
override val receiverType: ProtoBuf.Type? override val receiverType: ProtoBuf.Type?
get() = null get() = null
@@ -273,7 +261,7 @@ private class ConstructorClsStubBuilder(
val modifierListStubImpl = createModifierListStubForDeclaration(callableStub, constructorProto.flags, listOf(VISIBILITY)) val modifierListStubImpl = createModifierListStubForDeclaration(callableStub, constructorProto.flags, listOf(VISIBILITY))
val annotationIds = c.components.annotationLoader.loadCallableAnnotations( val annotationIds = c.components.annotationLoader.loadCallableAnnotations(
protoContainer, constructorProto, AnnotatedCallableKind.FUNCTION protoContainer, constructorProto, AnnotatedCallableKind.FUNCTION
) )
createAnnotationStubs(annotationIds, modifierListStubImpl) createAnnotationStubs(annotationIds, modifierListStubImpl)
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.stubBuilder package org.jetbrains.kotlin.idea.decompiler.stubBuilder
@@ -45,46 +34,47 @@ import org.jetbrains.kotlin.serialization.deserialization.getClassId
import org.jetbrains.kotlin.serialization.deserialization.getName import org.jetbrains.kotlin.serialization.deserialization.getName
fun createClassStub( fun createClassStub(
parent: StubElement<out PsiElement>, parent: StubElement<out PsiElement>,
classProto: ProtoBuf.Class, classProto: ProtoBuf.Class,
nameResolver: NameResolver, nameResolver: NameResolver,
classId: ClassId, classId: ClassId,
source: SourceElement?, source: SourceElement?,
context: ClsStubBuilderContext context: ClsStubBuilderContext
) { ) {
ClassClsStubBuilder(parent, classProto, nameResolver, classId, source, context).build() ClassClsStubBuilder(parent, classProto, nameResolver, classId, source, context).build()
} }
private class ClassClsStubBuilder( private class ClassClsStubBuilder(
private val parentStub: StubElement<out PsiElement>, private val parentStub: StubElement<out PsiElement>,
private val classProto: ProtoBuf.Class, private val classProto: ProtoBuf.Class,
nameResolver: NameResolver, nameResolver: NameResolver,
private val classId: ClassId, private val classId: ClassId,
source: SourceElement?, source: SourceElement?,
outerContext: ClsStubBuilderContext outerContext: ClsStubBuilderContext
) { ) {
private val thisAsProtoContainer = ProtoContainer.Class( private val thisAsProtoContainer = ProtoContainer.Class(
classProto, nameResolver, TypeTable(classProto.typeTable), source, outerContext.protoContainer classProto, nameResolver, TypeTable(classProto.typeTable), source, outerContext.protoContainer
) )
private val classKind = thisAsProtoContainer.kind private val classKind = thisAsProtoContainer.kind
private val c = outerContext.child( private val c = outerContext.child(
classProto.typeParameterList, classId.shortClassName, nameResolver, thisAsProtoContainer.typeTable, thisAsProtoContainer classProto.typeParameterList, classId.shortClassName, nameResolver, thisAsProtoContainer.typeTable, thisAsProtoContainer
) )
private val typeStubBuilder = TypeClsStubBuilder(c) private val typeStubBuilder = TypeClsStubBuilder(c)
private val supertypeIds = run { private val supertypeIds = run {
val supertypeIds = classProto.supertypes(c.typeTable).map { c.nameResolver.getClassId(it.className) } val supertypeIds = classProto.supertypes(c.typeTable).map { c.nameResolver.getClassId(it.className) }
//empty supertype list if single supertype is Any //empty supertype list if single supertype is Any
if (supertypeIds.singleOrNull()?.let { KotlinBuiltIns.FQ_NAMES.any == it.asSingleFqName().toUnsafe() } ?: false) { if (supertypeIds.singleOrNull()?.let { KotlinBuiltIns.FQ_NAMES.any == it.asSingleFqName().toUnsafe() } == true) {
listOf() listOf()
} } else {
else {
supertypeIds supertypeIds
} }
} }
private val companionObjectName = private val companionObjectName = if (classProto.hasCompanionObjectName())
if (classProto.hasCompanionObjectName()) c.nameResolver.getName(classProto.companionObjectName) else null c.nameResolver.getName(classProto.companionObjectName)
else
null
private val classOrObjectStub = createClassOrObjectStubAndModifierListStub() private val classOrObjectStub = createClassOrObjectStubAndModifierListStub()
@@ -134,24 +124,24 @@ private class ClassClsStubBuilder(
return when (classKind) { return when (classKind) {
ProtoBuf.Class.Kind.OBJECT, ProtoBuf.Class.Kind.COMPANION_OBJECT -> { ProtoBuf.Class.Kind.OBJECT, ProtoBuf.Class.Kind.COMPANION_OBJECT -> {
KotlinObjectStubImpl( KotlinObjectStubImpl(
parentStub, shortName, fqName, superTypeRefs, parentStub, shortName, fqName, superTypeRefs,
isTopLevel = !classId.isNestedClass, isTopLevel = !classId.isNestedClass,
isDefault = isCompanionObject, isDefault = isCompanionObject,
isLocal = false, isLocal = false,
isObjectLiteral = false isObjectLiteral = false
) )
} }
else -> { else -> {
KotlinClassStubImpl( KotlinClassStubImpl(
KtClassElementType.getStubType(classKind == ProtoBuf.Class.Kind.ENUM_ENTRY), KtClassElementType.getStubType(classKind == ProtoBuf.Class.Kind.ENUM_ENTRY),
parentStub, parentStub,
fqName.ref(), fqName.ref(),
shortName, shortName,
superTypeRefs, superTypeRefs,
isInterface = classKind == ProtoBuf.Class.Kind.INTERFACE, isInterface = classKind == ProtoBuf.Class.Kind.INTERFACE,
isEnumEntry = classKind == ProtoBuf.Class.Kind.ENUM_ENTRY, isEnumEntry = classKind == ProtoBuf.Class.Kind.ENUM_ENTRY,
isLocal = false, isLocal = false,
isTopLevel = !classId.isNestedClass isTopLevel = !classId.isNestedClass
) )
} }
} }
@@ -169,12 +159,11 @@ private class ClassClsStubBuilder(
// if single supertype is any then no delegation specifier list is needed // if single supertype is any then no delegation specifier list is needed
if (supertypeIds.isEmpty()) return if (supertypeIds.isEmpty()) return
val delegationSpecifierListStub = val delegationSpecifierListStub = KotlinPlaceHolderStubImpl<KtSuperTypeList>(classOrObjectStub, KtStubElementTypes.SUPER_TYPE_LIST)
KotlinPlaceHolderStubImpl<KtSuperTypeList>(classOrObjectStub, KtStubElementTypes.SUPER_TYPE_LIST)
classProto.supertypes(c.typeTable).forEach { type -> classProto.supertypes(c.typeTable).forEach { type ->
val superClassStub = KotlinPlaceHolderStubImpl<KtSuperTypeEntry>( val superClassStub = KotlinPlaceHolderStubImpl<KtSuperTypeEntry>(
delegationSpecifierListStub, KtStubElementTypes.SUPER_TYPE_ENTRY delegationSpecifierListStub, KtStubElementTypes.SUPER_TYPE_ENTRY
) )
typeStubBuilder.createTypeReferenceStub(superClassStub, type) typeStubBuilder.createTypeReferenceStub(superClassStub, type)
} }
@@ -204,15 +193,15 @@ private class ClassClsStubBuilder(
val name = c.nameResolver.getName(entry.name) val name = c.nameResolver.getName(entry.name)
val annotations = c.components.annotationLoader.loadEnumEntryAnnotations(thisAsProtoContainer, entry) val annotations = c.components.annotationLoader.loadEnumEntryAnnotations(thisAsProtoContainer, entry)
val enumEntryStub = KotlinClassStubImpl( val enumEntryStub = KotlinClassStubImpl(
KtStubElementTypes.ENUM_ENTRY, KtStubElementTypes.ENUM_ENTRY,
classBody, classBody,
qualifiedName = c.containerFqName.child(name).ref(), qualifiedName = c.containerFqName.child(name).ref(),
name = name.ref(), name = name.ref(),
superNames = arrayOf(), superNames = arrayOf(),
isInterface = false, isInterface = false,
isEnumEntry = true, isEnumEntry = true,
isLocal = false, isLocal = false,
isTopLevel = false isTopLevel = false
) )
if (annotations.isNotEmpty()) { if (annotations.isNotEmpty()) {
createAnnotationStubs(annotations, createEmptyModifierListStub(enumEntryStub)) createAnnotationStubs(annotations, createEmptyModifierListStub(enumEntryStub))
@@ -228,13 +217,14 @@ private class ClassClsStubBuilder(
} }
createDeclarationsStubs( createDeclarationsStubs(
classBody, c, thisAsProtoContainer, classProto.functionList, classProto.propertyList, classProto.typeAliasList) classBody, c, thisAsProtoContainer, classProto.functionList, classProto.propertyList, classProto.typeAliasList
)
} }
private fun isClass(): Boolean { private fun isClass(): Boolean {
return classKind == ProtoBuf.Class.Kind.CLASS || return classKind == ProtoBuf.Class.Kind.CLASS ||
classKind == ProtoBuf.Class.Kind.ENUM_CLASS || classKind == ProtoBuf.Class.Kind.ENUM_CLASS ||
classKind == ProtoBuf.Class.Kind.ANNOTATION_CLASS classKind == ProtoBuf.Class.Kind.ANNOTATION_CLASS
} }
private fun createInnerAndNestedClasses(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) { private fun createInnerAndNestedClasses(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) {
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.stubBuilder package org.jetbrains.kotlin.idea.decompiler.stubBuilder
@@ -32,24 +21,23 @@ import org.jetbrains.kotlin.serialization.deserialization.getName
data class ClassIdWithTarget(val classId: ClassId, val target: AnnotationUseSiteTarget?) data class ClassIdWithTarget(val classId: ClassId, val target: AnnotationUseSiteTarget?)
class ClsStubBuilderComponents( class ClsStubBuilderComponents(
val classDataFinder: ClassDataFinder, val classDataFinder: ClassDataFinder,
val annotationLoader: AnnotationAndConstantLoader<ClassId, Unit>, val annotationLoader: AnnotationAndConstantLoader<ClassId, Unit>,
val virtualFileForDebug: VirtualFile val virtualFileForDebug: VirtualFile
) { ) {
fun createContext( fun createContext(
nameResolver: NameResolver, nameResolver: NameResolver,
packageFqName: FqName, packageFqName: FqName,
typeTable: TypeTable typeTable: TypeTable
): ClsStubBuilderContext { ): ClsStubBuilderContext =
return ClsStubBuilderContext(this, nameResolver, packageFqName, EmptyTypeParameters, typeTable, protoContainer = null) ClsStubBuilderContext(this, nameResolver, packageFqName, EmptyTypeParameters, typeTable, protoContainer = null)
}
} }
interface TypeParameters { interface TypeParameters {
operator fun get(id: Int): Name operator fun get(id: Int): Name
fun child(nameResolver: NameResolver, innerTypeParameters: List<ProtoBuf.TypeParameter>) fun child(nameResolver: NameResolver, innerTypeParameters: List<ProtoBuf.TypeParameter>) =
= TypeParametersImpl(nameResolver, innerTypeParameters, parent = this) TypeParametersImpl(nameResolver, innerTypeParameters, parent = this)
} }
object EmptyTypeParameters : TypeParameters { object EmptyTypeParameters : TypeParameters {
@@ -57,9 +45,9 @@ object EmptyTypeParameters : TypeParameters {
} }
class TypeParametersImpl( class TypeParametersImpl(
nameResolver: NameResolver, nameResolver: NameResolver,
typeParameterProtos: Collection<ProtoBuf.TypeParameter>, typeParameterProtos: Collection<ProtoBuf.TypeParameter>,
private val parent: TypeParameters private val parent: TypeParameters
) : TypeParameters { ) : TypeParameters {
private val typeParametersById = typeParameterProtos.map { Pair(it.id, nameResolver.getName(it.name)) }.toMap() private val typeParametersById = typeParameterProtos.map { Pair(it.id, nameResolver.getName(it.name)) }.toMap()
@@ -67,27 +55,25 @@ class TypeParametersImpl(
} }
class ClsStubBuilderContext( class ClsStubBuilderContext(
val components: ClsStubBuilderComponents, val components: ClsStubBuilderComponents,
val nameResolver: NameResolver, val nameResolver: NameResolver,
val containerFqName: FqName, val containerFqName: FqName,
val typeParameters: TypeParameters, val typeParameters: TypeParameters,
val typeTable: TypeTable, val typeTable: TypeTable,
val protoContainer: ProtoContainer.Class? val protoContainer: ProtoContainer.Class?
) )
internal fun ClsStubBuilderContext.child( internal fun ClsStubBuilderContext.child(
typeParameterList: List<ProtoBuf.TypeParameter>, typeParameterList: List<ProtoBuf.TypeParameter>,
name: Name? = null, name: Name? = null,
nameResolver: NameResolver = this.nameResolver, nameResolver: NameResolver = this.nameResolver,
typeTable: TypeTable = this.typeTable, typeTable: TypeTable = this.typeTable,
protoContainer: ProtoContainer.Class? = this.protoContainer protoContainer: ProtoContainer.Class? = this.protoContainer
): ClsStubBuilderContext { ): ClsStubBuilderContext = ClsStubBuilderContext(
return ClsStubBuilderContext( this.components,
this.components, nameResolver,
nameResolver, if (name != null) this.containerFqName.child(name) else this.containerFqName,
if (name != null) this.containerFqName.child(name) else this.containerFqName, this.typeParameters.child(nameResolver, typeParameterList),
this.typeParameters.child(nameResolver, typeParameterList), typeTable,
typeTable, protoContainer
protoContainer )
)
}
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * 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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -36,7 +36,11 @@ import java.util.*
private val ANNOTATIONS_NOT_LOADED_FOR_TYPES = setOf(KotlinBuiltIns.FQ_NAMES.parameterName) private val ANNOTATIONS_NOT_LOADED_FOR_TYPES = setOf(KotlinBuiltIns.FQ_NAMES.parameterName)
class TypeClsStubBuilder(private val c: ClsStubBuilderContext) { class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
fun createTypeReferenceStub(parent: StubElement<out PsiElement>, type: Type, additionalAnnotations: () -> List<ClassIdWithTarget> = { emptyList() }) { fun createTypeReferenceStub(
parent: StubElement<out PsiElement>,
type: Type,
additionalAnnotations: () -> List<ClassIdWithTarget> = { emptyList() }
) {
val abbreviatedType = type.abbreviatedType(c.typeTable) val abbreviatedType = type.abbreviatedType(c.typeTable)
if (abbreviatedType != null) { if (abbreviatedType != null) {
return createTypeReferenceStub(parent, abbreviatedType, additionalAnnotations) return createTypeReferenceStub(parent, abbreviatedType, additionalAnnotations)
@@ -64,9 +68,10 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
} }
} }
private fun nullableTypeParent(parent: KotlinStubBaseImpl<*>, type: Type): KotlinStubBaseImpl<*> = private fun nullableTypeParent(parent: KotlinStubBaseImpl<*>, type: Type): KotlinStubBaseImpl<*> = if (type.nullable)
if (type.nullable) KotlinPlaceHolderStubImpl<KtNullableType>(parent, KtStubElementTypes.NULLABLE_TYPE) KotlinPlaceHolderStubImpl<KtNullableType>(parent, KtStubElementTypes.NULLABLE_TYPE)
else parent else
parent
private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List<ClassIdWithTarget>) { private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List<ClassIdWithTarget>) {
createTypeAnnotationStubs(parent, type, annotations) createTypeAnnotationStubs(parent, type, annotations)
@@ -88,11 +93,11 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
} }
val classId = c.nameResolver.getClassId(if (type.hasClassName()) type.className else type.typeAliasName) val classId = c.nameResolver.getClassId(if (type.hasClassName()) type.className else type.typeAliasName)
val shouldBuildAsFunctionType = isBuiltinFunctionClass(classId) val shouldBuildAsFunctionType = isBuiltinFunctionClass(classId) && type.argumentList.none { it.projection == Projection.STAR }
&& type.argumentList.none { it.projection == Projection.STAR }
if (shouldBuildAsFunctionType) { if (shouldBuildAsFunctionType) {
val (extensionAnnotations, notExtensionAnnotations) = val (extensionAnnotations, notExtensionAnnotations) = annotations.partition {
annotations.partition { it.classId.asSingleFqName() == KotlinBuiltIns.FQ_NAMES.extensionFunctionType } it.classId.asSingleFqName() == KotlinBuiltIns.FQ_NAMES.extensionFunctionType
}
val isExtension = extensionAnnotations.isNotEmpty() val isExtension = extensionAnnotations.isNotEmpty()
val isSuspend = Flags.SUSPEND_TYPE.get(type.flags) val isSuspend = Flags.SUSPEND_TYPE.get(type.flags)
@@ -101,8 +106,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
val wrapper = nullableTypeParent(parent, type) val wrapper = nullableTypeParent(parent, type)
createTypeAnnotationStubs(wrapper, type, notExtensionAnnotations) createTypeAnnotationStubs(wrapper, type, notExtensionAnnotations)
wrapper wrapper
} } else {
else {
createTypeAnnotationStubs(parent, type, notExtensionAnnotations) createTypeAnnotationStubs(parent, type, notExtensionAnnotations)
nullableTypeParent(parent, type) nullableTypeParent(parent, type)
} }
@@ -116,8 +120,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
val outerTypeChain = generateSequence(type) { it.outerType(c.typeTable) }.toList() val outerTypeChain = generateSequence(type) { it.outerType(c.typeTable) }.toList()
createStubForTypeName(classId, nullableTypeParent(parent, type)) { createStubForTypeName(classId, nullableTypeParent(parent, type)) { userTypeStub, index ->
userTypeStub, index ->
outerTypeChain.getOrNull(index)?.let { createTypeArgumentListStub(userTypeStub, it.argumentList) } outerTypeChain.getOrNull(index)?.let { createTypeArgumentListStub(userTypeStub, it.argumentList) }
} }
} }
@@ -165,19 +168,24 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
Projection.STAR -> KtProjectionKind.STAR Projection.STAR -> KtProjectionKind.STAR
} }
private fun createFunctionTypeStub(parent: StubElement<out PsiElement>, type: Type, isExtensionFunctionType: Boolean, isSuspend: Boolean) { private fun createFunctionTypeStub(
parent: StubElement<out PsiElement>,
type: Type,
isExtensionFunctionType: Boolean,
isSuspend: Boolean
) {
val typeArgumentList = type.argumentList val typeArgumentList = type.argumentList
val functionType = KotlinPlaceHolderStubImpl<KtFunctionType>(parent, KtStubElementTypes.FUNCTION_TYPE) val functionType = KotlinPlaceHolderStubImpl<KtFunctionType>(parent, KtStubElementTypes.FUNCTION_TYPE)
if (isExtensionFunctionType) { if (isExtensionFunctionType) {
val functionTypeReceiverStub val functionTypeReceiverStub =
= KotlinPlaceHolderStubImpl<KtFunctionTypeReceiver>(functionType, KtStubElementTypes.FUNCTION_TYPE_RECEIVER) KotlinPlaceHolderStubImpl<KtFunctionTypeReceiver>(functionType, KtStubElementTypes.FUNCTION_TYPE_RECEIVER)
val receiverTypeProto = typeArgumentList.first().type(c.typeTable)!! val receiverTypeProto = typeArgumentList.first().type(c.typeTable)!!
createTypeReferenceStub(functionTypeReceiverStub, receiverTypeProto) createTypeReferenceStub(functionTypeReceiverStub, receiverTypeProto)
} }
val parameterList = KotlinPlaceHolderStubImpl<KtParameterList>(functionType, KtStubElementTypes.VALUE_PARAMETER_LIST) val parameterList = KotlinPlaceHolderStubImpl<KtParameterList>(functionType, KtStubElementTypes.VALUE_PARAMETER_LIST)
val typeArgumentsWithoutReceiverAndReturnType val typeArgumentsWithoutReceiverAndReturnType =
= typeArgumentList.subList(if (isExtensionFunctionType) 1 else 0, typeArgumentList.size - 1) typeArgumentList.subList(if (isExtensionFunctionType) 1 else 0, typeArgumentList.size - 1)
var suspendParameterType: Type? = null var suspendParameterType: Type? = null
for ((index, argument) in typeArgumentsWithoutReceiverAndReturnType.withIndex()) { for ((index, argument) in typeArgumentsWithoutReceiverAndReturnType.withIndex()) {
@@ -197,7 +205,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
} }
} }
val parameter = KotlinParameterStubImpl( val parameter = KotlinParameterStubImpl(
parameterList, fqName = null, name = null, isMutable = false, hasValOrVar = false, hasDefaultValue = false parameterList, fqName = null, name = null, isMutable = false, hasValOrVar = false, hasDefaultValue = false
) )
createTypeReferenceStub(parameter, argument.type(c.typeTable)!!) createTypeReferenceStub(parameter, argument.type(c.typeTable)!!)
@@ -207,41 +215,46 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
if (suspendParameterType == null) { if (suspendParameterType == null) {
val returnType = typeArgumentList.last().type(c.typeTable)!! val returnType = typeArgumentList.last().type(c.typeTable)!!
createTypeReferenceStub(functionType, returnType) createTypeReferenceStub(functionType, returnType)
} } else {
else {
val continuationArgumentType = suspendParameterType.getArgument(0).type(c.typeTable)!! val continuationArgumentType = suspendParameterType.getArgument(0).type(c.typeTable)!!
createTypeReferenceStub(functionType, continuationArgumentType) createTypeReferenceStub(functionType, continuationArgumentType)
} }
} }
fun createValueParameterListStub( fun createValueParameterListStub(
parent: StubElement<out PsiElement>, parent: StubElement<out PsiElement>,
callableProto: MessageLite, callableProto: MessageLite,
parameters: List<ProtoBuf.ValueParameter>, parameters: List<ProtoBuf.ValueParameter>,
container: ProtoContainer container: ProtoContainer
) { ) {
val parameterListStub = KotlinPlaceHolderStubImpl<KtParameterList>(parent, KtStubElementTypes.VALUE_PARAMETER_LIST) val parameterListStub = KotlinPlaceHolderStubImpl<KtParameterList>(parent, KtStubElementTypes.VALUE_PARAMETER_LIST)
for ((index, valueParameterProto) in parameters.withIndex()) { for ((index, valueParameterProto) in parameters.withIndex()) {
val name = c.nameResolver.getName(valueParameterProto.name) val name = c.nameResolver.getName(valueParameterProto.name)
val parameterStub = KotlinParameterStubImpl( val parameterStub = KotlinParameterStubImpl(
parameterListStub, parameterListStub,
name = name.ref(), name = name.ref(),
fqName = null, fqName = null,
hasDefaultValue = false, hasDefaultValue = false,
hasValOrVar = false, hasValOrVar = false,
isMutable = false isMutable = false
) )
val varargElementType = valueParameterProto.varargElementType(c.typeTable) val varargElementType = valueParameterProto.varargElementType(c.typeTable)
val typeProto = varargElementType ?: valueParameterProto.type(c.typeTable) val typeProto = varargElementType ?: valueParameterProto.type(c.typeTable)
val modifiers = arrayListOf<KtModifierKeywordToken>() val modifiers = arrayListOf<KtModifierKeywordToken>()
if (varargElementType != null) { modifiers.add(KtTokens.VARARG_KEYWORD) } if (varargElementType != null) {
if (Flags.IS_CROSSINLINE.get(valueParameterProto.flags)) { modifiers.add(KtTokens.CROSSINLINE_KEYWORD) } modifiers.add(KtTokens.VARARG_KEYWORD)
if (Flags.IS_NOINLINE.get(valueParameterProto.flags)) { modifiers.add(KtTokens.NOINLINE_KEYWORD) } }
if (Flags.IS_CROSSINLINE.get(valueParameterProto.flags)) {
modifiers.add(KtTokens.CROSSINLINE_KEYWORD)
}
if (Flags.IS_NOINLINE.get(valueParameterProto.flags)) {
modifiers.add(KtTokens.NOINLINE_KEYWORD)
}
val modifierList = createModifierListStub(parameterStub, modifiers) val modifierList = createModifierListStub(parameterStub, modifiers)
val parameterAnnotations = c.components.annotationLoader.loadValueParameterAnnotations( val parameterAnnotations = c.components.annotationLoader.loadValueParameterAnnotations(
container, callableProto, callableProto.annotatedCallableKind, index, valueParameterProto container, callableProto, callableProto.annotatedCallableKind, index, valueParameterProto
) )
if (parameterAnnotations.isNotEmpty()) { if (parameterAnnotations.isNotEmpty()) {
createAnnotationStubs(parameterAnnotations, modifierList ?: createEmptyModifierListStub(parameterStub)) createAnnotationStubs(parameterAnnotations, modifierList ?: createEmptyModifierListStub(parameterStub))
@@ -252,8 +265,8 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
} }
fun createTypeParameterListStub( fun createTypeParameterListStub(
parent: StubElement<out PsiElement>, parent: StubElement<out PsiElement>,
typeParameterProtoList: List<ProtoBuf.TypeParameter> typeParameterProtoList: List<ProtoBuf.TypeParameter>
): List<Pair<Name, Type>> { ): List<Pair<Name, Type>> {
if (typeParameterProtoList.isEmpty()) return listOf() if (typeParameterProtoList.isEmpty()) return listOf()
@@ -262,10 +275,10 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
for (proto in typeParameterProtoList) { for (proto in typeParameterProtoList) {
val name = c.nameResolver.getName(proto.name) val name = c.nameResolver.getName(proto.name)
val typeParameterStub = KotlinTypeParameterStubImpl( val typeParameterStub = KotlinTypeParameterStubImpl(
typeParameterListStub, typeParameterListStub,
name = name.ref(), name = name.ref(),
isInVariance = proto.variance == Variance.IN, isInVariance = proto.variance == Variance.IN,
isOutVariance = proto.variance == Variance.OUT isOutVariance = proto.variance == Variance.OUT
) )
createTypeParameterModifierListStub(typeParameterStub, proto) createTypeParameterModifierListStub(typeParameterStub, proto)
val upperBoundProtos = proto.upperBounds(c.typeTable) val upperBoundProtos = proto.upperBounds(c.typeTable)
@@ -281,8 +294,8 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
} }
fun createTypeConstraintListStub( fun createTypeConstraintListStub(
parent: StubElement<out PsiElement>, parent: StubElement<out PsiElement>,
protosForTypeConstraintList: List<Pair<Name, Type>> protosForTypeConstraintList: List<Pair<Name, Type>>
) { ) {
if (protosForTypeConstraintList.isEmpty()) { if (protosForTypeConstraintList.isEmpty()) {
return return
@@ -296,15 +309,17 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
} }
private fun createTypeParameterModifierListStub( private fun createTypeParameterModifierListStub(
typeParameterStub: KotlinTypeParameterStubImpl, typeParameterStub: KotlinTypeParameterStubImpl,
typeParameterProto: ProtoBuf.TypeParameter typeParameterProto: ProtoBuf.TypeParameter
) { ) {
val modifiers = ArrayList<KtModifierKeywordToken>() val modifiers = ArrayList<KtModifierKeywordToken>()
when (typeParameterProto.variance) { when (typeParameterProto.variance) {
Variance.IN -> modifiers.add(KtTokens.IN_KEYWORD) Variance.IN -> modifiers.add(KtTokens.IN_KEYWORD)
Variance.OUT -> modifiers.add(KtTokens.OUT_KEYWORD) Variance.OUT -> modifiers.add(KtTokens.OUT_KEYWORD)
Variance.INV -> { /* do nothing */ } Variance.INV -> { /* do nothing */
null -> { /* do nothing */ } }
null -> { /* do nothing */
}
} }
if (typeParameterProto.reified) { if (typeParameterProto.reified) {
modifiers.add(KtTokens.REIFIED_KEYWORD) modifiers.add(KtTokens.REIFIED_KEYWORD)
@@ -315,14 +330,15 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
val annotations = c.components.annotationLoader.loadTypeParameterAnnotations(typeParameterProto, c.nameResolver) val annotations = c.components.annotationLoader.loadTypeParameterAnnotations(typeParameterProto, c.nameResolver)
if (annotations.isNotEmpty()) { if (annotations.isNotEmpty()) {
createAnnotationStubs( createAnnotationStubs(
annotations, annotations,
modifierList ?: createEmptyModifierListStub(typeParameterStub)) modifierList ?: createEmptyModifierListStub(typeParameterStub)
)
} }
} }
private fun Type.isDefaultUpperBound(): Boolean { private fun Type.isDefaultUpperBound(): Boolean {
return this.hasClassName() && return this.hasClassName() &&
c.nameResolver.getClassId(className).let { KotlinBuiltIns.FQ_NAMES.any == it.asSingleFqName().toUnsafe() } && c.nameResolver.getClassId(className).let { KotlinBuiltIns.FQ_NAMES.any == it.asSingleFqName().toUnsafe() } &&
this.nullable this.nullable
} }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.stubBuilder package org.jetbrains.kotlin.idea.decompiler.stubBuilder
@@ -43,11 +32,11 @@ import org.jetbrains.kotlin.serialization.deserialization.AnnotatedCallableKind
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
fun createTopLevelClassStub( fun createTopLevelClassStub(
classId: ClassId, classId: ClassId,
classProto: ProtoBuf.Class, classProto: ProtoBuf.Class,
source: SourceElement?, source: SourceElement?,
context: ClsStubBuilderContext, context: ClsStubBuilderContext,
isScript: Boolean isScript: Boolean
): KotlinFileStubImpl { ): KotlinFileStubImpl {
val fileStub = createFileStub(classId.packageFqName, isScript) val fileStub = createFileStub(classId.packageFqName, isScript)
createClassStub(fileStub, classProto, context.nameResolver, classId, source, context) createClassStub(fileStub, classProto, context.nameResolver, classId, source, context)
@@ -55,21 +44,22 @@ fun createTopLevelClassStub(
} }
fun createPackageFacadeStub( fun createPackageFacadeStub(
packageProto: ProtoBuf.Package, packageProto: ProtoBuf.Package,
packageFqName: FqName, packageFqName: FqName,
c: ClsStubBuilderContext c: ClsStubBuilderContext
): KotlinFileStubImpl { ): KotlinFileStubImpl {
val fileStub = KotlinFileStubForIde.forFile(packageFqName, isScript = false) val fileStub = KotlinFileStubForIde.forFile(packageFqName, isScript = false)
setupFileStub(fileStub, packageFqName) setupFileStub(fileStub, packageFqName)
createDeclarationsStubs( createDeclarationsStubs(
fileStub, c, ProtoContainer.Package(packageFqName, c.nameResolver, c.typeTable, source = null), packageProto) fileStub, c, ProtoContainer.Package(packageFqName, c.nameResolver, c.typeTable, source = null), packageProto
)
return fileStub return fileStub
} }
fun createFileFacadeStub( fun createFileFacadeStub(
packageProto: ProtoBuf.Package, packageProto: ProtoBuf.Package,
facadeFqName: FqName, facadeFqName: FqName,
c: ClsStubBuilderContext c: ClsStubBuilderContext
): KotlinFileStubImpl { ): KotlinFileStubImpl {
val packageFqName = facadeFqName.parent() val packageFqName = facadeFqName.parent()
val fileStub = KotlinFileStubForIde.forFileFacadeStub(facadeFqName) val fileStub = KotlinFileStubForIde.forFileFacadeStub(facadeFqName)
@@ -83,10 +73,10 @@ fun createFileFacadeStub(
} }
fun createMultifileClassStub( fun createMultifileClassStub(
header: KotlinClassHeader, header: KotlinClassHeader,
partFiles: List<KotlinJvmBinaryClass>, partFiles: List<KotlinJvmBinaryClass>,
facadeFqName: FqName, facadeFqName: FqName,
components: ClsStubBuilderComponents components: ClsStubBuilderComponents
): KotlinFileStubImpl { ): KotlinFileStubImpl {
val packageFqName = facadeFqName.parent() val packageFqName = facadeFqName.parent()
val partNames = header.data?.asList()?.map { it.substringAfterLast('/') } val partNames = header.data?.asList()?.map { it.substringAfterLast('/') }
@@ -143,15 +133,15 @@ fun createStubForPackageName(packageDirectiveStub: KotlinPlaceHolderStubImpl<KtP
} }
fun createStubForTypeName( fun createStubForTypeName(
typeClassId: ClassId, typeClassId: ClassId,
parent: StubElement<out PsiElement>, parent: StubElement<out PsiElement>,
bindTypeArguments: (KotlinUserTypeStub, Int) -> Unit = { _, _ -> } bindTypeArguments: (KotlinUserTypeStub, Int) -> Unit = { _, _ -> }
): KotlinUserTypeStub { ): KotlinUserTypeStub {
val substituteWithAny = typeClassId.isLocal val substituteWithAny = typeClassId.isLocal
val fqName = val fqName = if (substituteWithAny) KotlinBuiltIns.FQ_NAMES.any
if (substituteWithAny) KotlinBuiltIns.FQ_NAMES.any else typeClassId.asSingleFqName().toUnsafe()
else typeClassId.asSingleFqName().toUnsafe()
val segments = fqName.pathSegments().asReversed() val segments = fqName.pathSegments().asReversed()
assert(segments.isNotEmpty()) assert(segments.isNotEmpty())
@@ -172,10 +162,10 @@ fun createStubForTypeName(
} }
fun createModifierListStubForDeclaration( fun createModifierListStubForDeclaration(
parent: StubElement<out PsiElement>, parent: StubElement<out PsiElement>,
flags: Int, flags: Int,
flagsToTranslate: List<FlagsToModifiers> = listOf(), flagsToTranslate: List<FlagsToModifiers> = listOf(),
additionalModifiers: List<KtModifierKeywordToken> = listOf() additionalModifiers: List<KtModifierKeywordToken> = listOf()
): KotlinModifierListStubImpl { ): KotlinModifierListStubImpl {
assert(flagsToTranslate.isNotEmpty()) assert(flagsToTranslate.isNotEmpty())
@@ -184,24 +174,24 @@ fun createModifierListStubForDeclaration(
} }
fun createModifierListStub( fun createModifierListStub(
parent: StubElement<out PsiElement>, parent: StubElement<out PsiElement>,
modifiers: Collection<KtModifierKeywordToken> modifiers: Collection<KtModifierKeywordToken>
): KotlinModifierListStubImpl? { ): KotlinModifierListStubImpl? {
if (modifiers.isEmpty()) { if (modifiers.isEmpty()) {
return null return null
} }
return KotlinModifierListStubImpl( return KotlinModifierListStubImpl(
parent, parent,
ModifierMaskUtils.computeMask { it in modifiers }, ModifierMaskUtils.computeMask { it in modifiers },
KtStubElementTypes.MODIFIER_LIST KtStubElementTypes.MODIFIER_LIST
) )
} }
fun createEmptyModifierListStub(parent: KotlinStubBaseImpl<*>): KotlinModifierListStubImpl { fun createEmptyModifierListStub(parent: KotlinStubBaseImpl<*>): KotlinModifierListStubImpl {
return KotlinModifierListStubImpl( return KotlinModifierListStubImpl(
parent, parent,
ModifierMaskUtils.computeMask { false }, ModifierMaskUtils.computeMask { false },
KtStubElementTypes.MODIFIER_LIST KtStubElementTypes.MODIFIER_LIST
) )
} }
@@ -210,34 +200,33 @@ fun createAnnotationStubs(annotationIds: List<ClassId>, parent: KotlinStubBaseIm
} }
fun createTargetedAnnotationStubs( fun createTargetedAnnotationStubs(
annotationIds: List<ClassIdWithTarget>, annotationIds: List<ClassIdWithTarget>,
parent: KotlinStubBaseImpl<*> parent: KotlinStubBaseImpl<*>
) { ) {
if (annotationIds.isEmpty()) return if (annotationIds.isEmpty()) return
annotationIds.forEach { annotation -> annotationIds.forEach { annotation ->
val (annotationClassId, target) = annotation val (annotationClassId, target) = annotation
val annotationEntryStubImpl = KotlinAnnotationEntryStubImpl( val annotationEntryStubImpl = KotlinAnnotationEntryStubImpl(
parent, parent,
shortName = annotationClassId.shortClassName.ref(), shortName = annotationClassId.shortClassName.ref(),
hasValueArguments = false hasValueArguments = false
) )
if (target != null) { if (target != null) {
KotlinAnnotationUseSiteTargetStubImpl(annotationEntryStubImpl, StringRef.fromString(target.name)!!) KotlinAnnotationUseSiteTargetStubImpl(annotationEntryStubImpl, StringRef.fromString(target.name)!!)
} }
val constructorCallee = KotlinPlaceHolderStubImpl<KtConstructorCalleeExpression>(annotationEntryStubImpl, KtStubElementTypes.CONSTRUCTOR_CALLEE) val constructorCallee =
KotlinPlaceHolderStubImpl<KtConstructorCalleeExpression>(annotationEntryStubImpl, KtStubElementTypes.CONSTRUCTOR_CALLEE)
val typeReference = KotlinPlaceHolderStubImpl<KtTypeReference>(constructorCallee, KtStubElementTypes.TYPE_REFERENCE) val typeReference = KotlinPlaceHolderStubImpl<KtTypeReference>(constructorCallee, KtStubElementTypes.TYPE_REFERENCE)
createStubForTypeName(annotationClassId, typeReference) createStubForTypeName(annotationClassId, typeReference)
} }
} }
val MessageLite.annotatedCallableKind: AnnotatedCallableKind val MessageLite.annotatedCallableKind: AnnotatedCallableKind
get() { get() = when (this) {
return when (this) { is ProtoBuf.Property -> AnnotatedCallableKind.PROPERTY
is ProtoBuf.Property -> AnnotatedCallableKind.PROPERTY is ProtoBuf.Function, is ProtoBuf.Constructor -> AnnotatedCallableKind.FUNCTION
is ProtoBuf.Function, is ProtoBuf.Constructor -> AnnotatedCallableKind.FUNCTION else -> throw IllegalStateException("Unsupported message: $this")
else -> throw IllegalStateException("Unsupported message: $this")
}
} }
fun Name.ref() = StringRef.fromString(this.asString())!! fun Name.ref() = StringRef.fromString(this.asString())!!
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.stubBuilder.flags package org.jetbrains.kotlin.idea.decompiler.stubBuilder.flags
@@ -66,12 +55,12 @@ val TAILREC = createBooleanFlagToModifier(Flags.IS_TAILREC, KtTokens.TAILREC_KEY
val SUSPEND = createBooleanFlagToModifier(Flags.IS_SUSPEND, KtTokens.SUSPEND_KEYWORD) val SUSPEND = createBooleanFlagToModifier(Flags.IS_SUSPEND, KtTokens.SUSPEND_KEYWORD)
private fun createBooleanFlagToModifier( private fun createBooleanFlagToModifier(
flagField: Flags.BooleanFlagField, ktModifierKeywordToken: KtModifierKeywordToken flagField: Flags.BooleanFlagField, ktModifierKeywordToken: KtModifierKeywordToken
): FlagsToModifiers = BooleanFlagToModifier(flagField, ktModifierKeywordToken) ): FlagsToModifiers = BooleanFlagToModifier(flagField, ktModifierKeywordToken)
private class BooleanFlagToModifier( private class BooleanFlagToModifier(
private val flagField: Flags.BooleanFlagField, private val flagField: Flags.BooleanFlagField,
private val ktModifierKeywordToken: KtModifierKeywordToken private val ktModifierKeywordToken: KtModifierKeywordToken
) : FlagsToModifiers() { ) : FlagsToModifiers() {
override fun getModifiers(flags: Int): KtModifierKeywordToken? = if (flagField.get(flags)) ktModifierKeywordToken else null override fun getModifiers(flags: Int): KtModifierKeywordToken? = if (flagField.get(flags)) ktModifierKeywordToken else null
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.stubBuilder package org.jetbrains.kotlin.idea.decompiler.stubBuilder
@@ -21,18 +10,18 @@ import com.intellij.psi.stubs.StubElement
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.flags.VISIBILITY import org.jetbrains.kotlin.idea.decompiler.stubBuilder.flags.VISIBILITY
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.Flags import org.jetbrains.kotlin.metadata.deserialization.Flags
import org.jetbrains.kotlin.metadata.deserialization.underlyingType
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.stubs.impl.KotlinTypeAliasStubImpl import org.jetbrains.kotlin.psi.stubs.impl.KotlinTypeAliasStubImpl
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
import org.jetbrains.kotlin.serialization.deserialization.getClassId import org.jetbrains.kotlin.serialization.deserialization.getClassId
import org.jetbrains.kotlin.serialization.deserialization.getName import org.jetbrains.kotlin.serialization.deserialization.getName
import org.jetbrains.kotlin.metadata.deserialization.underlyingType
fun createTypeAliasStub( fun createTypeAliasStub(
parent: StubElement<out PsiElement>, parent: StubElement<out PsiElement>,
typeAliasProto: ProtoBuf.TypeAlias, typeAliasProto: ProtoBuf.TypeAlias,
protoContainer: ProtoContainer, protoContainer: ProtoContainer,
context: ClsStubBuilderContext context: ClsStubBuilderContext
) { ) {
val shortName = context.nameResolver.getName(typeAliasProto.name) val shortName = context.nameResolver.getName(typeAliasProto.name)
@@ -41,10 +30,10 @@ fun createTypeAliasStub(
is ProtoContainer.Package -> ClassId.topLevel(protoContainer.fqName.child(shortName)) is ProtoContainer.Package -> ClassId.topLevel(protoContainer.fqName.child(shortName))
} }
val typeAlias = val typeAlias = KotlinTypeAliasStubImpl(
KotlinTypeAliasStubImpl( parent, classId.shortClassName.ref(), classId.asSingleFqName().ref(),
parent, classId.shortClassName.ref(), classId.asSingleFqName().ref(), isTopLevel = !classId.isNestedClass
isTopLevel = !classId.isNestedClass) )
val modifierList = createModifierListStubForDeclaration(typeAlias, typeAliasProto.flags, arrayListOf(VISIBILITY), listOf()) val modifierList = createModifierListStubForDeclaration(typeAlias, typeAliasProto.flags, arrayListOf(VISIBILITY), listOf())
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.textBuilder package org.jetbrains.kotlin.idea.decompiler.textBuilder
@@ -22,7 +11,7 @@ import org.jetbrains.kotlin.utils.keysToMap
data class DecompiledText(val text: String, val index: DecompiledTextIndex) data class DecompiledText(val text: String, val index: DecompiledTextIndex)
interface DecompiledTextIndexer<out T: Any> { interface DecompiledTextIndexer<out T : Any> {
fun indexDescriptor(descriptor: DeclarationDescriptor): Collection<T> fun indexDescriptor(descriptor: DeclarationDescriptor): Collection<T>
} }
@@ -33,16 +22,14 @@ class DecompiledTextIndex(private val indexers: Collection<DecompiledTextIndexer
fun addToIndex(descriptor: DeclarationDescriptor, textRange: TextRange) { fun addToIndex(descriptor: DeclarationDescriptor, textRange: TextRange) {
indexers.forEach { mapper -> indexers.forEach { mapper ->
val correspondingMap = indexerToMap[mapper]!! val correspondingMap = indexerToMap.getValue(mapper)
mapper.indexDescriptor(descriptor).forEach { key -> mapper.indexDescriptor(descriptor).forEach { key ->
correspondingMap[key] = textRange correspondingMap[key] = textRange
} }
} }
} }
fun <T: Any> getRange(mapper: DecompiledTextIndexer<T>, key: T): TextRange? { fun <T : Any> getRange(mapper: DecompiledTextIndexer<T>, key: T): TextRange? = indexerToMap[mapper]?.get(key)
return indexerToMap[mapper]?.get(key)
}
companion object { companion object {
val Empty = DecompiledTextIndex(listOf()) val Empty = DecompiledTextIndex(listOf())
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.textBuilder package org.jetbrains.kotlin.idea.decompiler.textBuilder
@@ -52,7 +41,7 @@ abstract class DeserializerForDecompilerBase(val directoryPackageFqName: FqName)
override fun resolveTopLevelClass(classId: ClassId) = deserializationComponents.deserializeClass(classId) override fun resolveTopLevelClass(classId: ClassId) = deserializationComponents.deserializeClass(classId)
protected fun createDummyPackageFragment(fqName: FqName): MutablePackageFragmentDescriptor = protected fun createDummyPackageFragment(fqName: FqName): MutablePackageFragmentDescriptor =
MutablePackageFragmentDescriptor(moduleDescriptor, fqName) MutablePackageFragmentDescriptor(moduleDescriptor, fqName)
private fun createDummyModule(name: String) = ModuleDescriptorImpl(Name.special("<$name>"), storageManager, builtIns) private fun createDummyModule(name: String) = ModuleDescriptorImpl(Name.special("<$name>"), storageManager, builtIns)
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.decompiler.textBuilder package org.jetbrains.kotlin.idea.decompiler.textBuilder
@@ -29,10 +18,10 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry
import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors
import org.jetbrains.kotlin.types.isFlexible import org.jetbrains.kotlin.types.isFlexible
private val DECOMPILED_CODE_COMMENT = "/* compiled code */" private const val DECOMPILED_CODE_COMMENT = "/* compiled code */"
private val DECOMPILED_COMMENT_FOR_PARAMETER = "/* = compiled code */" private const val DECOMPILED_COMMENT_FOR_PARAMETER = "/* = compiled code */"
private val FLEXIBLE_TYPE_COMMENT = "/* platform type */" private const val FLEXIBLE_TYPE_COMMENT = "/* platform type */"
private val DECOMPILED_CONTRACT_STUB = "contract { /* compiled contract */ }" private const val DECOMPILED_CONTRACT_STUB = "contract { /* compiled contract */ }"
fun DescriptorRendererOptions.defaultDecompilerRendererOptions() { fun DescriptorRendererOptions.defaultDecompilerRendererOptions() {
withDefinedIn = false withDefinedIn = false
@@ -45,10 +34,10 @@ fun DescriptorRendererOptions.defaultDecompilerRendererOptions() {
} }
fun buildDecompiledText( fun buildDecompiledText(
packageFqName: FqName, packageFqName: FqName,
descriptors: List<DeclarationDescriptor>, descriptors: List<DeclarationDescriptor>,
descriptorRenderer: DescriptorRenderer, descriptorRenderer: DescriptorRenderer,
indexers: Collection<DecompiledTextIndexer<*>> = listOf(ByDescriptorIndexer) indexers: Collection<DecompiledTextIndexer<*>> = listOf(ByDescriptorIndexer)
): DecompiledText { ): DecompiledText {
val builder = StringBuilder() val builder = StringBuilder()
@@ -75,8 +64,7 @@ fun buildDecompiledText(
} }
builder.append(descriptor.name.asString()) builder.append(descriptor.name.asString())
builder.append(if (lastEnumEntry!!) ";" else ",") builder.append(if (lastEnumEntry!!) ";" else ",")
} } else {
else {
builder.append(descriptorRenderer.render(descriptor).replace("= ...", DECOMPILED_COMMENT_FOR_PARAMETER)) builder.append(descriptorRenderer.render(descriptor).replace("= ...", DECOMPILED_COMMENT_FOR_PARAMETER))
} }
var endOffset = builder.length var endOffset = builder.length
@@ -98,25 +86,22 @@ fun buildDecompiledText(
} }
append(DECOMPILED_CODE_COMMENT).append(" }") append(DECOMPILED_CODE_COMMENT).append(" }")
} }
} } else {
else {
// descriptor instanceof PropertyDescriptor // descriptor instanceof PropertyDescriptor
builder.append(" ").append(DECOMPILED_CODE_COMMENT) builder.append(" ").append(DECOMPILED_CODE_COMMENT)
} }
endOffset = builder.length endOffset = builder.length
} }
} } else if (descriptor is ClassDescriptor && !isEnumEntry(descriptor)) {
else if (descriptor is ClassDescriptor && !isEnumEntry(descriptor)) {
builder.append(" {\n") builder.append(" {\n")
val subindent = indent + " " val subindent = "$indent "
var firstPassed = false var firstPassed = false
fun newlineExceptFirst() { fun newlineExceptFirst() {
if (firstPassed) { if (firstPassed) {
builder.append("\n") builder.append("\n")
} } else {
else {
firstPassed = true firstPassed = true
} }
} }
@@ -147,7 +132,8 @@ fun buildDecompiledText(
if (member is CallableMemberDescriptor if (member is CallableMemberDescriptor
&& member.kind != CallableMemberDescriptor.Kind.DECLARATION && member.kind != CallableMemberDescriptor.Kind.DECLARATION
//TODO: not synthesized and component like //TODO: not synthesized and component like
&& !DataClassDescriptorResolver.isComponentLike(member.name)) { && !DataClassDescriptorResolver.isComponentLike(member.name)
) {
continue continue
} }
newlineExceptFirst() newlineExceptFirst()
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.facet package org.jetbrains.kotlin.idea.facet
@@ -20,11 +9,13 @@ import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.module.Module import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.ModuleRootModel import com.intellij.openapi.roots.ModuleRootModel
import com.intellij.util.text.VersionComparatorUtil import com.intellij.util.text.VersionComparatorUtil
import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.platform.IdePlatformKind import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider
import org.jetbrains.kotlin.platform.orDefault import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.VersionView import org.jetbrains.kotlin.config.VersionView
import org.jetbrains.kotlin.platform.IdePlatformKind
import org.jetbrains.kotlin.platform.idePlatformKind import org.jetbrains.kotlin.platform.idePlatformKind
import org.jetbrains.kotlin.platform.orDefault
interface KotlinVersionInfoProvider { interface KotlinVersionInfoProvider {
companion object { companion object {
@@ -43,18 +34,16 @@ fun getRuntimeLibraryVersions(
module: Module, module: Module,
rootModel: ModuleRootModel?, rootModel: ModuleRootModel?,
platformKind: IdePlatformKind<*> platformKind: IdePlatformKind<*>
): Collection<String> { ): Collection<String> = KotlinVersionInfoProvider.EP_NAME
return KotlinVersionInfoProvider.EP_NAME .extensions
.extensions .map { it.getLibraryVersions(module, platformKind, rootModel) }
.map { it.getLibraryVersions(module, platformKind, rootModel) } .firstOrNull { it.isNotEmpty() } ?: emptyList()
.firstOrNull { it.isNotEmpty() } ?: emptyList()
}
fun getLibraryLanguageLevel( fun getLibraryLanguageLevel(
module: Module, module: Module,
rootModel: ModuleRootModel?, rootModel: ModuleRootModel?,
platformKind: IdePlatformKind<*>?, platformKind: IdePlatformKind<*>?,
coerceRuntimeLibraryVersionToReleased: Boolean = true coerceRuntimeLibraryVersionToReleased: Boolean = true
): LanguageVersion { ): LanguageVersion {
val minVersion = getRuntimeLibraryVersions(module, rootModel, platformKind.orDefault()) val minVersion = getRuntimeLibraryVersions(module, rootModel, platformKind.orDefault())
.addReleaseVersionIfNecessary(coerceRuntimeLibraryVersionToReleased) .addReleaseVersionIfNecessary(coerceRuntimeLibraryVersionToReleased)
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.findUsages package org.jetbrains.kotlin.idea.findUsages
@@ -44,14 +33,10 @@ object UsageTypeUtils {
val context = refExpr.analyze(BodyResolveMode.PARTIAL) val context = refExpr.analyze(BodyResolveMode.PARTIAL)
fun getCommonUsageType(): UsageTypeEnum? { fun getCommonUsageType(): UsageTypeEnum? = when {
return when { refExpr.getNonStrictParentOfType<KtImportDirective>() != null -> CLASS_IMPORT
refExpr.getNonStrictParentOfType<KtImportDirective>() != null -> refExpr.getParentOfTypeAndBranch<KtCallableReferenceExpression>() { callableReference } != null -> CALLABLE_REFERENCE
CLASS_IMPORT else -> null
refExpr.getParentOfTypeAndBranch<KtCallableReferenceExpression>(){ callableReference } != null ->
CALLABLE_REFERENCE
else -> null
}
} }
fun getClassUsageType(): UsageTypeEnum? { fun getClassUsageType(): UsageTypeEnum? {
@@ -79,26 +64,18 @@ object UsageTypeUtils {
} }
return when { return when {
refExpr.getParentOfTypeAndBranch<KtTypeParameter>(){ extendsBound } != null refExpr.getParentOfTypeAndBranch<KtTypeParameter>() { extendsBound } != null || refExpr.getParentOfTypeAndBranch<KtTypeConstraint>() { boundTypeReference } != null -> TYPE_CONSTRAINT
|| refExpr.getParentOfTypeAndBranch<KtTypeConstraint>(){ boundTypeReference } != null ->
TYPE_CONSTRAINT
refExpr is KtSuperTypeListEntry refExpr is KtSuperTypeListEntry || refExpr.getParentOfTypeAndBranch<KtSuperTypeListEntry>() { typeReference } != null -> SUPER_TYPE
|| refExpr.getParentOfTypeAndBranch<KtSuperTypeListEntry>(){ typeReference } != null ->
SUPER_TYPE
refExpr.getParentOfTypeAndBranch<KtParameter>(){ typeReference } != null -> refExpr.getParentOfTypeAndBranch<KtParameter>() { typeReference } != null -> VALUE_PARAMETER_TYPE
VALUE_PARAMETER_TYPE
refExpr.getParentOfTypeAndBranch<KtIsExpression>(){ typeReference } != null refExpr.getParentOfTypeAndBranch<KtIsExpression>() { typeReference } != null || refExpr.getParentOfTypeAndBranch<KtWhenConditionIsPattern>() { typeReference } != null -> IS
|| refExpr.getParentOfTypeAndBranch<KtWhenConditionIsPattern>(){ typeReference } != null ->
IS
with(refExpr.getParentOfTypeAndBranch<KtBinaryExpressionWithTypeRHS>(){ right }) { with(refExpr.getParentOfTypeAndBranch<KtBinaryExpressionWithTypeRHS>() { right }) {
val opType = this?.operationReference?.getReferencedNameElementType() val opType = this?.operationReference?.getReferencedNameElementType()
opType == KtTokens.AS_KEYWORD || opType == KtTokens.AS_SAFE opType == KtTokens.AS_KEYWORD || opType == KtTokens.AS_SAFE
} -> } -> CLASS_CAST_TO
CLASS_CAST_TO
with(refExpr.getNonStrictParentOfType<KtDotQualifiedExpression>()) { with(refExpr.getNonStrictParentOfType<KtDotQualifiedExpression>()) {
when { when {
@@ -110,26 +87,21 @@ object UsageTypeUtils {
} }
else -> { else -> {
selectorExpression == refExpr selectorExpression == refExpr
&& getParentOfTypeAndBranch<KtDotQualifiedExpression>(strict = true) { receiverExpression } != null && getParentOfTypeAndBranch<KtDotQualifiedExpression>(strict = true) { receiverExpression } != null
} }
} }
} -> } -> CLASS_OBJECT_ACCESS
CLASS_OBJECT_ACCESS
refExpr.getParentOfTypeAndBranch<KtSuperExpression>(){ superTypeQualifier } != null -> refExpr.getParentOfTypeAndBranch<KtSuperExpression>() { superTypeQualifier } != null -> SUPER_TYPE_QUALIFIER
SUPER_TYPE_QUALIFIER
refExpr.getParentOfTypeAndBranch<KtTypeAlias> { getTypeReference() } != null -> refExpr.getParentOfTypeAndBranch<KtTypeAlias> { getTypeReference() } != null -> TYPE_ALIAS
TYPE_ALIAS
else -> null else -> null
} }
} }
fun getVariableUsageType(): UsageTypeEnum? { fun getVariableUsageType(): UsageTypeEnum? {
if (refExpr.getParentOfTypeAndBranch<KtDelegatedSuperTypeEntry>(){ delegateExpression } != null) { if (refExpr.getParentOfTypeAndBranch<KtDelegatedSuperTypeEntry>() { delegateExpression } != null) return DELEGATE
return DELEGATE
}
if (refExpr.parent is KtValueArgumentName) return NAMED_ARGUMENT if (refExpr.parent is KtValueArgumentName) return NAMED_ARGUMENT
@@ -165,43 +137,32 @@ object UsageTypeUtils {
} }
return when { return when {
refExpr.getParentOfTypeAndBranch<KtSuperTypeListEntry>(){ typeReference } != null -> refExpr.getParentOfTypeAndBranch<KtSuperTypeListEntry>() { typeReference } != null -> SUPER_TYPE
SUPER_TYPE
descriptor is ConstructorDescriptor descriptor is ConstructorDescriptor && refExpr.getParentOfTypeAndBranch<KtAnnotationEntry>() { typeReference } != null -> ANNOTATION
&& refExpr.getParentOfTypeAndBranch<KtAnnotationEntry>(){ typeReference } != null ->
ANNOTATION
with(refExpr.getParentOfTypeAndBranch<KtCallExpression>(){ calleeExpression }) { with(refExpr.getParentOfTypeAndBranch<KtCallExpression>() { calleeExpression }) {
this?.calleeExpression is KtSimpleNameExpression this?.calleeExpression is KtSimpleNameExpression
} -> } -> if (descriptor is ConstructorDescriptor) CLASS_NEW_OPERATOR else FUNCTION_CALL
if (descriptor is ConstructorDescriptor) CLASS_NEW_OPERATOR else FUNCTION_CALL
refExpr.getParentOfTypeAndBranch<KtBinaryExpression>(){ operationReference } != null || refExpr.getParentOfTypeAndBranch<KtBinaryExpression>() { operationReference } != null || refExpr.getParentOfTypeAndBranch<KtUnaryExpression>() { operationReference } != null || refExpr.getParentOfTypeAndBranch<KtWhenConditionInRange>() { operationReference } != null -> FUNCTION_CALL
refExpr.getParentOfTypeAndBranch<KtUnaryExpression>(){ operationReference } != null ||
refExpr.getParentOfTypeAndBranch<KtWhenConditionInRange>(){ operationReference } != null ->
FUNCTION_CALL
else -> null else -> null
} }
} }
fun getPackageUsageType(): UsageTypeEnum? { fun getPackageUsageType(): UsageTypeEnum? = when {
return when { refExpr.getNonStrictParentOfType<KtPackageDirective>() != null -> PACKAGE_DIRECTIVE
refExpr.getNonStrictParentOfType<KtPackageDirective>() != null -> PACKAGE_DIRECTIVE refExpr.getNonStrictParentOfType<KtQualifiedExpression>() != null -> PACKAGE_MEMBER_ACCESS
refExpr.getNonStrictParentOfType<KtQualifiedExpression>() != null -> PACKAGE_MEMBER_ACCESS else -> getClassUsageType()
else -> getClassUsageType()
}
} }
val usageType = getCommonUsageType() val usageType = getCommonUsageType()
if (usageType != null) return usageType if (usageType != null) return usageType
val descriptor = context[BindingContext.REFERENCE_TARGET, refExpr] return when (val descriptor = context[BindingContext.REFERENCE_TARGET, refExpr]) {
return when (descriptor) {
is ClassifierDescriptor -> when { is ClassifierDescriptor -> when {
// Treat object accesses as variables to simulate the old behaviour (when variables were created for objects) // Treat object accesses as variables to simulate the old behaviour (when variables were created for objects)
DescriptorUtils.isNonCompanionObject(descriptor) || DescriptorUtils.isEnumEntry(descriptor) -> getVariableUsageType() DescriptorUtils.isNonCompanionObject(descriptor) || DescriptorUtils.isEnumEntry(descriptor) -> getVariableUsageType()
DescriptorUtils.isCompanionObject(descriptor) -> COMPANION_OBJECT_ACCESS DescriptorUtils.isCompanionObject(descriptor) -> COMPANION_OBJECT_ACCESS
else -> getClassUsageType() else -> getClassUsageType()
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * 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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -19,9 +19,11 @@ object CommonLibraryType : LibraryType<DummyLibraryProperties>(CommonLibraryKind
override fun getCreateActionName() = null override fun getCreateActionName() = null
override fun createNewLibrary(parentComponent: JComponent, override fun createNewLibrary(
contextDirectory: VirtualFile?, parentComponent: JComponent,
project: Project): NewLibraryConfiguration? = null contextDirectory: VirtualFile?,
project: Project
): NewLibraryConfiguration? = null
override fun getIcon(properties: DummyLibraryProperties?) = KotlinIcons.MPP override fun getIcon(properties: DummyLibraryProperties?) = KotlinIcons.MPP
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.framework package org.jetbrains.kotlin.idea.framework
@@ -28,7 +17,6 @@ import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.utils.LibraryUtils import org.jetbrains.kotlin.utils.LibraryUtils
import org.jetbrains.kotlin.utils.PathUtil import org.jetbrains.kotlin.utils.PathUtil
import java.io.File import java.io.File
import java.util.*
import java.util.jar.Attributes import java.util.jar.Attributes
object JsLibraryStdDetectionUtil { object JsLibraryStdDetectionUtil {
@@ -56,7 +44,8 @@ object JsLibraryStdDetectionUtil {
val name = root.url.substringBefore("!/").substringAfterLast('/') val name = root.url.substringBefore("!/").substringAfterLast('/')
if (name == PathUtil.JS_LIB_JAR_NAME || name == PathUtil.JS_LIB_10_JAR_NAME || if (name == PathUtil.JS_LIB_JAR_NAME || name == PathUtil.JS_LIB_10_JAR_NAME ||
PathUtil.KOTLIN_STDLIB_JS_JAR_PATTERN.matcher(name).matches() || PathUtil.KOTLIN_STDLIB_JS_JAR_PATTERN.matcher(name).matches() ||
PathUtil.KOTLIN_JS_LIBRARY_JAR_PATTERN.matcher(name).matches()) { PathUtil.KOTLIN_JS_LIBRARY_JAR_PATTERN.matcher(name).matches()
) {
val jar = VfsUtilCore.getVirtualFileForJar(root) ?: continue val jar = VfsUtilCore.getVirtualFileForJar(root) ?: continue
var isJSStdLib = jar.getUserData(IS_JS_LIBRARY_STD_LIB) var isJSStdLib = jar.getUserData(IS_JS_LIBRARY_STD_LIB)
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.highlighter package org.jetbrains.kotlin.idea.highlighter
@@ -82,7 +71,8 @@ internal class BeforeResolveHighlightingVisitor(holder: AnnotationHolder) : High
override fun visitArgument(argument: KtValueArgument) { override fun visitArgument(argument: KtValueArgument) {
val argumentName = argument.getArgumentName() ?: return val argumentName = argument.getArgumentName() ?: return
val eq = argument.equalsToken ?: return val eq = argument.equalsToken ?: return
createInfoAnnotation(TextRange(argumentName.startOffset, eq.endOffset), null).textAttributes = KotlinHighlightingColors.NAMED_ARGUMENT createInfoAnnotation(TextRange(argumentName.startOffset, eq.endOffset), null).textAttributes =
KotlinHighlightingColors.NAMED_ARGUMENT
} }
override fun visitExpressionWithLabel(expression: KtExpressionWithLabel) { override fun visitExpressionWithLabel(expression: KtExpressionWithLabel) {
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.highlighter package org.jetbrains.kotlin.idea.highlighter
@@ -45,7 +34,7 @@ class DebugInfoAnnotator : Annotator {
DebugInfoUtil.markDebugAnnotations(element, bindingContext, object : DebugInfoUtil.DebugInfoReporter() { DebugInfoUtil.markDebugAnnotations(element, bindingContext, object : DebugInfoUtil.DebugInfoReporter() {
override fun reportElementWithErrorType(expression: KtReferenceExpression) { override fun reportElementWithErrorType(expression: KtReferenceExpression) {
holder.createErrorAnnotation(expression, "[DEBUG] Resolved to error element").textAttributes = holder.createErrorAnnotation(expression, "[DEBUG] Resolved to error element").textAttributes =
KotlinHighlightingColors.RESOLVED_TO_ERROR KotlinHighlightingColors.RESOLVED_TO_ERROR
} }
override fun reportMissingUnresolved(expression: KtReferenceExpression) { override fun reportMissingUnresolved(expression: KtReferenceExpression) {
@@ -56,9 +45,8 @@ class DebugInfoAnnotator : Annotator {
} }
override fun reportUnresolvedWithTarget(expression: KtReferenceExpression, target: String) { override fun reportUnresolvedWithTarget(expression: KtReferenceExpression, target: String) {
holder.createErrorAnnotation(expression, "[DEBUG] Reference marked as unresolved is actually resolved to " + target) holder.createErrorAnnotation(expression, "[DEBUG] Reference marked as unresolved is actually resolved to $target")
.textAttributes = .textAttributes = KotlinHighlightingColors.DEBUG_INFO
KotlinHighlightingColors.DEBUG_INFO
} }
}) })
} catch (e: ProcessCanceledException) { } catch (e: ProcessCanceledException) {
@@ -74,6 +62,7 @@ class DebugInfoAnnotator : Annotator {
companion object { companion object {
val isDebugInfoEnabled: Boolean val isDebugInfoEnabled: Boolean
get() = ApplicationManager.getApplication().isInternal && (KotlinPluginUtil.isSnapshotVersion() || KotlinPluginUtil.isDevVersion()) get() = ApplicationManager.getApplication()
.isInternal && (KotlinPluginUtil.isSnapshotVersion() || KotlinPluginUtil.isDevVersion())
} }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.highlighter package org.jetbrains.kotlin.idea.highlighter
@@ -37,7 +26,7 @@ import org.jetbrains.kotlin.serialization.deserialization.KOTLIN_SUSPEND_BUILT_I
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
internal class FunctionsHighlightingVisitor(holder: AnnotationHolder, bindingContext: BindingContext) : internal class FunctionsHighlightingVisitor(holder: AnnotationHolder, bindingContext: BindingContext) :
AfterAnalysisHighlightingVisitor(holder, bindingContext) { AfterAnalysisHighlightingVisitor(holder, bindingContext) {
override fun visitNamedFunction(function: KtNamedFunction) { override fun visitNamedFunction(function: KtNamedFunction) {
function.nameIdentifier?.let { highlightName(it, FUNCTION_DECLARATION) } function.nameIdentifier?.let { highlightName(it, FUNCTION_DECLARATION) }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.highlighter package org.jetbrains.kotlin.idea.highlighter
@@ -25,8 +14,8 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
abstract class HighlighterExtension { abstract class HighlighterExtension {
abstract fun highlightDeclaration(elementToHighlight: PsiElement, descriptor: DeclarationDescriptor): TextAttributesKey? abstract fun highlightDeclaration(elementToHighlight: PsiElement, descriptor: DeclarationDescriptor): TextAttributesKey?
open fun highlightCall(elementToHighlight: PsiElement, resolvedCall: ResolvedCall<*>): TextAttributesKey? open fun highlightCall(elementToHighlight: PsiElement, resolvedCall: ResolvedCall<*>): TextAttributesKey? =
= highlightDeclaration(elementToHighlight, resolvedCall.resultingDescriptor) highlightDeclaration(elementToHighlight, resolvedCall.resultingDescriptor)
companion object { companion object {
val EP_NAME = ExtensionPointName.create<HighlighterExtension>("org.jetbrains.kotlin.highlighterExtension") val EP_NAME = ExtensionPointName.create<HighlighterExtension>("org.jetbrains.kotlin.highlighterExtension")
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.highlighter package org.jetbrains.kotlin.idea.highlighter
@@ -40,7 +29,7 @@ object IdeRenderers {
@JvmField @JvmField
val HTML_RENDER_TYPE = SmartTypeRenderer(DescriptorRenderer.HTML.withOptions { val HTML_RENDER_TYPE = SmartTypeRenderer(DescriptorRenderer.HTML.withOptions {
parameterNamesInFunctionalTypes = false parameterNamesInFunctionalTypes = false
modifiers = DescriptorRendererModifier.ALL_EXCEPT_ANNOTATIONS modifiers = DescriptorRendererModifier.ALL_EXCEPT_ANNOTATIONS
}) })
@JvmField @JvmField
@@ -86,7 +75,8 @@ object IdeRenderers {
val context = RenderingContext.of(descriptors) val context = RenderingContext.of(descriptors)
val conflicts = descriptors.joinToString("") { "<li>" + HTML.render(it, context) + "</li>\n" } val conflicts = descriptors.joinToString("") { "<li>" + HTML.render(it, context) + "</li>\n" }
"The following declarations have the same JVM signature (<code>${data.signature.name}${data.signature.desc}</code>):<br/>\n<ul>\n$conflicts</ul>" "The following declarations have the same JVM signature (<code>${data.signature.name}${data.signature
.desc}</code>):<br/>\n<ul>\n$conflicts</ul>"
} }
@JvmField @JvmField
@@ -98,8 +88,12 @@ object IdeRenderers {
val HTML = DescriptorRenderer.HTML.withOptions { val HTML = DescriptorRenderer.HTML.withOptions {
modifiers = DescriptorRendererModifier.ALL_EXCEPT_ANNOTATIONS modifiers = DescriptorRendererModifier.ALL_EXCEPT_ANNOTATIONS
}.asRenderer() }.asRenderer()
@JvmField val HTML_WITH_ANNOTATIONS = DescriptorRenderer.HTML.withOptions {
@JvmField
val HTML_WITH_ANNOTATIONS = DescriptorRenderer.HTML.withOptions {
modifiers = DescriptorRendererModifier.ALL modifiers = DescriptorRendererModifier.ALL
}.asRenderer() }.asRenderer()
@JvmField val HTML_WITH_ANNOTATIONS_WHITELIST = DescriptorRenderer.HTML.withAnnotationsWhitelist()
@JvmField
val HTML_WITH_ANNOTATIONS_WHITELIST = DescriptorRenderer.HTML.withAnnotationsWhitelist()
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.highlighter package org.jetbrains.kotlin.idea.highlighter
@@ -35,16 +24,17 @@ import com.intellij.psi.PsiRecursiveElementVisitor
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
class KotlinBeforeResolveHighlightingPass( class KotlinBeforeResolveHighlightingPass(
private val file: KtFile, private val file: KtFile,
document: Document document: Document
) : TextEditorHighlightingPass(file.project, document), DumbAware { ) : TextEditorHighlightingPass(file.project, document), DumbAware {
@Volatile private var annotationHolder: AnnotationHolderImpl? = null @Volatile
private var annotationHolder: AnnotationHolderImpl? = null
override fun doCollectInformation(progress: ProgressIndicator) { override fun doCollectInformation(progress: ProgressIndicator) {
val annotationHolder = AnnotationHolderImpl(AnnotationSession(file)) val annotationHolder = AnnotationHolderImpl(AnnotationSession(file))
val visitor = BeforeResolveHighlightingVisitor(annotationHolder) val visitor = BeforeResolveHighlightingVisitor(annotationHolder)
file.accept(object : PsiRecursiveElementVisitor(){ file.accept(object : PsiRecursiveElementVisitor() {
override fun visitElement(element: PsiElement) { override fun visitElement(element: PsiElement) {
super.visitElement(element) super.visitElement(element)
element.accept(visitor) element.accept(visitor)
@@ -64,7 +54,13 @@ class KotlinBeforeResolveHighlightingPass(
class Factory(registrar: TextEditorHighlightingPassRegistrar) : ProjectComponent, TextEditorHighlightingPassFactory { class Factory(registrar: TextEditorHighlightingPassRegistrar) : ProjectComponent, TextEditorHighlightingPassFactory {
init { init {
registrar.registerTextEditorHighlightingPass(this, TextEditorHighlightingPassRegistrar.Anchor.BEFORE, Pass.UPDATE_FOLDING, false, false) registrar.registerTextEditorHighlightingPass(
this,
TextEditorHighlightingPassRegistrar.Anchor.BEFORE,
Pass.UPDATE_FOLDING,
false,
false
)
} }
override fun createHighlightingPass(file: PsiFile, editor: Editor): TextEditorHighlightingPass? { override fun createHighlightingPass(file: PsiFile, editor: Editor): TextEditorHighlightingPass? {
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.highlighter package org.jetbrains.kotlin.idea.highlighter
@@ -28,11 +17,11 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import java.util.* import java.util.*
class KotlinSuppressableWarningProblemGroup( class KotlinSuppressableWarningProblemGroup(
private val diagnosticFactory: DiagnosticFactory<*> private val diagnosticFactory: DiagnosticFactory<*>
) : SuppressableProblemGroup { ) : SuppressableProblemGroup {
init { init {
assert (diagnosticFactory.severity == Severity.WARNING) assert(diagnosticFactory.severity == Severity.WARNING)
} }
override fun getProblemName() = diagnosticFactory.name override fun getProblemName() = diagnosticFactory.name
@@ -47,7 +36,7 @@ class KotlinSuppressableWarningProblemGroup(
} }
fun createSuppressWarningActions(element: PsiElement, diagnosticFactory: DiagnosticFactory<*>): List<SuppressIntentionAction> = fun createSuppressWarningActions(element: PsiElement, diagnosticFactory: DiagnosticFactory<*>): List<SuppressIntentionAction> =
createSuppressWarningActions(element, diagnosticFactory.severity, diagnosticFactory.name) createSuppressWarningActions(element, diagnosticFactory.severity, diagnosticFactory.name)
fun createSuppressWarningActions(element: PsiElement, severity: Severity, suppressionKey: String): List<SuppressIntentionAction> { fun createSuppressWarningActions(element: PsiElement, severity: Severity, suppressionKey: String): List<SuppressIntentionAction> {
@@ -71,15 +60,17 @@ fun createSuppressWarningActions(element: PsiElement, severity: Severity, suppre
// Add suppress action at first statement // Add suppress action at first statement
if (current.parent is KtBlockExpression || current.parent is KtDestructuringDeclaration) { if (current.parent is KtBlockExpression || current.parent is KtDestructuringDeclaration) {
val kind = if (current.parent is KtBlockExpression) "statement" else "initializer" val kind = if (current.parent is KtBlockExpression) "statement" else "initializer"
actions.add(KotlinSuppressIntentionAction(current, suppressionKey, actions.add(
AnnotationHostKind(kind, "", true))) KotlinSuppressIntentionAction(current, suppressionKey, AnnotationHostKind(kind, "", true))
)
suppressAtStatementAllowed = false suppressAtStatementAllowed = false
} }
} }
current is KtFile -> { current is KtFile -> {
actions.add(KotlinSuppressIntentionAction(current, suppressionKey, actions.add(
AnnotationHostKind("file", current.name, true))) KotlinSuppressIntentionAction(current, suppressionKey, AnnotationHostKind("file", current.name, true))
)
suppressAtStatementAllowed = false suppressAtStatementAllowed = false
} }
} }
@@ -101,8 +92,8 @@ private object DeclarationKindDetector : KtVisitor<AnnotationHostKind?, Unit?>()
override fun visitProperty(d: KtProperty, data: Unit?) = detect(d, d.valOrVarKeyword.text!!) override fun visitProperty(d: KtProperty, data: Unit?) = detect(d, d.valOrVarKeyword.text!!)
override fun visitDestructuringDeclaration(d: KtDestructuringDeclaration, data: Unit?) = detect(d, d.valOrVarKeyword?.text ?: "val", override fun visitDestructuringDeclaration(d: KtDestructuringDeclaration, data: Unit?) =
name = d.entries.joinToString(", ", "(", ")") { it.name!! }) detect(d, d.valOrVarKeyword?.text ?: "val", name = d.entries.joinToString(", ", "(", ")") { it.name!! })
override fun visitTypeParameter(d: KtTypeParameter, data: Unit?) = detect(d, "type parameter", newLineNeeded = false) override fun visitTypeParameter(d: KtTypeParameter, data: Unit?) = detect(d, "type parameter", newLineNeeded = false)
@@ -110,7 +101,8 @@ private object DeclarationKindDetector : KtVisitor<AnnotationHostKind?, Unit?>()
override fun visitParameter(d: KtParameter, data: Unit?) = detect(d, "parameter", newLineNeeded = false) override fun visitParameter(d: KtParameter, data: Unit?) = detect(d, "parameter", newLineNeeded = false)
override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor, data: Unit?) = detect(constructor, "secondary constructor of") override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor, data: Unit?) =
detect(constructor, "secondary constructor of")
override fun visitObjectDeclaration(d: KtObjectDeclaration, data: Unit?): AnnotationHostKind? { override fun visitObjectDeclaration(d: KtObjectDeclaration, data: Unit?): AnnotationHostKind? {
if (d.isCompanion()) return detect(d, "companion object", name = "${d.name} of ${d.getStrictParentOfType<KtClass>()?.name}") if (d.isCompanion()) return detect(d, "companion object", name = "${d.name} of ${d.getStrictParentOfType<KtClass>()?.name}")
@@ -118,6 +110,10 @@ private object DeclarationKindDetector : KtVisitor<AnnotationHostKind?, Unit?>()
return detect(d, "object") return detect(d, "object")
} }
private fun detect(declaration: KtDeclaration, kind: String, name: String = declaration.name ?: "<anonymous>", newLineNeeded: Boolean = true) private fun detect(
= AnnotationHostKind(kind, name, newLineNeeded) declaration: KtDeclaration,
kind: String,
name: String = declaration.name ?: "<anonymous>",
newLineNeeded: Boolean = true
) = AnnotationHostKind(kind, name, newLineNeeded)
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2000-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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -91,26 +91,24 @@ internal class PropertiesHighlightingVisitor(holder: AnnotationHolder, bindingCo
} }
} }
private fun attributeKeyByPropertyType(descriptor: PropertyDescriptor): TextAttributesKey? { private fun attributeKeyByPropertyType(descriptor: PropertyDescriptor): TextAttributesKey? = when {
return when { descriptor.isDynamic() ->
descriptor.isDynamic() -> // The property is set in VariablesHighlightingVisitor
// The property is set in VariablesHighlightingVisitor null
null
KotlinHighlightingUtil.hasExtensionReceiverParameter(descriptor) -> KotlinHighlightingUtil.hasExtensionReceiverParameter(descriptor) ->
if (descriptor.isSynthesized) SYNTHETIC_EXTENSION_PROPERTY else EXTENSION_PROPERTY if (descriptor.isSynthesized) SYNTHETIC_EXTENSION_PROPERTY else EXTENSION_PROPERTY
DescriptorUtils.isStaticDeclaration(descriptor) -> DescriptorUtils.isStaticDeclaration(descriptor) ->
if(KotlinHighlightingUtil.hasCustomPropertyDeclaration(descriptor)) if (KotlinHighlightingUtil.hasCustomPropertyDeclaration(descriptor))
PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION
else else
PACKAGE_PROPERTY PACKAGE_PROPERTY
else -> else ->
if (KotlinHighlightingUtil.hasCustomPropertyDeclaration(descriptor)) if (KotlinHighlightingUtil.hasCustomPropertyDeclaration(descriptor))
INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION
else else
INSTANCE_PROPERTY INSTANCE_PROPERTY
}
} }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.highlighter package org.jetbrains.kotlin.idea.highlighter
@@ -37,8 +26,8 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
import org.jetbrains.kotlin.types.expressions.CaptureKind import org.jetbrains.kotlin.types.expressions.CaptureKind
internal class VariablesHighlightingVisitor(holder: AnnotationHolder, bindingContext: BindingContext) internal class VariablesHighlightingVisitor(holder: AnnotationHolder, bindingContext: BindingContext) :
: AfterAnalysisHighlightingVisitor(holder, bindingContext) { AfterAnalysisHighlightingVisitor(holder, bindingContext) {
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) { override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
val target = bindingContext.get(REFERENCE_TARGET, expression) ?: return val target = bindingContext.get(REFERENCE_TARGET, expression) ?: return
@@ -91,31 +80,32 @@ internal class VariablesHighlightingVisitor(holder: AnnotationHolder, bindingCon
is ImplicitClassReceiver -> "Implicit receiver" is ImplicitClassReceiver -> "Implicit receiver"
else -> "Unknown receiver" else -> "Unknown receiver"
} }
createInfoAnnotation(expression, createInfoAnnotation(
"$receiverName smart cast to " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type)) expression,
.textAttributes = SMART_CAST_RECEIVER "$receiverName smart cast to " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type)
).textAttributes = SMART_CAST_RECEIVER
} }
} }
val nullSmartCast = bindingContext.get(SMARTCAST_NULL, expression) == true val nullSmartCast = bindingContext.get(SMARTCAST_NULL, expression) == true
if (nullSmartCast) { if (nullSmartCast) {
createInfoAnnotation(expression, "Always null") createInfoAnnotation(expression, "Always null").textAttributes = SMART_CONSTANT
.textAttributes = SMART_CONSTANT
} }
val smartCast = bindingContext.get(SMARTCAST, expression) val smartCast = bindingContext.get(SMARTCAST, expression)
if (smartCast != null) { if (smartCast != null) {
val defaultType = smartCast.defaultType val defaultType = smartCast.defaultType
if (defaultType != null) { if (defaultType != null) {
createInfoAnnotation(getSmartCastTarget(expression), createInfoAnnotation(
"Smart cast to " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(defaultType)) getSmartCastTarget(expression),
.textAttributes = SMART_CAST_VALUE "Smart cast to " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(defaultType)
} ).textAttributes = SMART_CAST_VALUE
else if (smartCast is MultipleSmartCasts) { } else if (smartCast is MultipleSmartCasts) {
for ((call, type) in smartCast.map) { for ((call, type) in smartCast.map) {
createInfoAnnotation(getSmartCastTarget(expression), createInfoAnnotation(
"Smart cast to ${DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type)} (for $call call)") getSmartCastTarget(expression),
.textAttributes = SMART_CAST_VALUE "Smart cast to ${DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type)} (for $call call)"
).textAttributes = SMART_CAST_VALUE
} }
} }
} }
@@ -166,11 +156,13 @@ internal class VariablesHighlightingVisitor(holder: AnnotationHolder, bindingCon
if (descriptor is PropertyDescriptor && KotlinHighlightingUtil.hasCustomPropertyDeclaration(descriptor)) { if (descriptor is PropertyDescriptor && KotlinHighlightingUtil.hasCustomPropertyDeclaration(descriptor)) {
val isStaticDeclaration = DescriptorUtils.isStaticDeclaration(descriptor) val isStaticDeclaration = DescriptorUtils.isStaticDeclaration(descriptor)
highlightName(elementToHighlight, highlightName(
if (isStaticDeclaration) elementToHighlight,
PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION if (isStaticDeclaration)
else PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION
INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION) else
INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION
)
} }
} }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.highlighter.renderersUtil package org.jetbrains.kotlin.idea.highlighter.renderersUtil
@@ -32,8 +21,8 @@ import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.ErrorUtils
private val RED_TEMPLATE = "<font color=red><b>%s</b></font>" private const val RED_TEMPLATE = "<font color=red><b>%s</b></font>"
private val STRONG_TEMPLATE = "<b>%s</b>" private const val STRONG_TEMPLATE = "<b>%s</b>"
fun renderStrong(o: Any): String = STRONG_TEMPLATE.format(o) fun renderStrong(o: Any): String = STRONG_TEMPLATE.format(o)
@@ -59,21 +48,19 @@ fun renderResolvedCall(resolvedCall: ResolvedCall<*>, context: RenderingContext)
fun renderParameter(parameter: ValueParameterDescriptor): String { fun renderParameter(parameter: ValueParameterDescriptor): String {
val varargElementType = parameter.varargElementType val varargElementType = parameter.varargElementType
val parameterType = varargElementType ?: parameter.type val parameterType = varargElementType ?: parameter.type
val renderedParameter = val renderedParameter = (if (varargElementType != null) "<b>vararg</b> " else "") +
(if (varargElementType != null) "<b>vararg</b> " else "") +
typeRenderer.render(parameterType, context) + typeRenderer.render(parameterType, context) +
if (parameter.hasDefaultValue()) " = ..." else "" if (parameter.hasDefaultValue()) " = ..." else ""
if (resolvedCall.hasTypeMismatchErrorOnParameter(parameter)) { return if (resolvedCall.hasTypeMismatchErrorOnParameter(parameter))
return renderError(renderedParameter) renderError(renderedParameter)
} else
return renderedParameter renderedParameter
} }
fun appendTypeParametersSubstitution() { fun appendTypeParametersSubstitution() {
val parametersToArgumentsMap = resolvedCall.typeArguments val parametersToArgumentsMap = resolvedCall.typeArguments
fun TypeParameterDescriptor.isInferred(): Boolean { fun TypeParameterDescriptor.isInferred(): Boolean {
val typeArgument = parametersToArgumentsMap[this] val typeArgument = parametersToArgumentsMap[this] ?: return false
if (typeArgument == null) return false
return !ErrorUtils.isUninferredParameter(typeArgument) return !ErrorUtils.isUninferredParameter(typeArgument)
} }
@@ -81,16 +68,16 @@ fun renderResolvedCall(resolvedCall: ResolvedCall<*>, context: RenderingContext)
val (inferredTypeParameters, notInferredTypeParameters) = typeParameters.partition(TypeParameterDescriptor::isInferred) val (inferredTypeParameters, notInferredTypeParameters) = typeParameters.partition(TypeParameterDescriptor::isInferred)
append("<br/>$indent<i>where</i> ") append("<br/>$indent<i>where</i> ")
if (!notInferredTypeParameters.isEmpty()) { if (notInferredTypeParameters.isNotEmpty()) {
append(notInferredTypeParameters.joinToString { typeParameter -> renderError(typeParameter.name) }) append(notInferredTypeParameters.joinToString { typeParameter -> renderError(typeParameter.name) })
append("<i> cannot be inferred</i>") append("<i> cannot be inferred</i>")
if (!inferredTypeParameters.isEmpty()) { if (inferredTypeParameters.isNotEmpty()) {
append("; ") append("; ")
} }
} }
val typeParameterToTypeArgumentMap = resolvedCall.typeArguments val typeParameterToTypeArgumentMap = resolvedCall.typeArguments
if (!inferredTypeParameters.isEmpty()) { if (inferredTypeParameters.isNotEmpty()) {
append(inferredTypeParameters.joinToString { typeParameter -> append(inferredTypeParameters.joinToString { typeParameter ->
"${typeParameter.name} = ${typeRenderer.render(typeParameterToTypeArgumentMap[typeParameter]!!, context)}" "${typeParameter.name} = ${typeRenderer.render(typeParameterToTypeArgumentMap[typeParameter]!!, context)}"
}) })
@@ -106,13 +93,12 @@ fun renderResolvedCall(resolvedCall: ResolvedCall<*>, context: RenderingContext)
append(resultingDescriptor.valueParameters.joinToString(transform = ::renderParameter)) append(resultingDescriptor.valueParameters.joinToString(transform = ::renderParameter))
append(if (resolvedCall.hasUnmappedArguments()) renderError(")") else ")") append(if (resolvedCall.hasUnmappedArguments()) renderError(")") else ")")
if (!resolvedCall.candidateDescriptor.typeParameters.isEmpty()) { if (resolvedCall.candidateDescriptor.typeParameters.isNotEmpty()) {
appendTypeParametersSubstitution() appendTypeParametersSubstitution()
append("<i> for </i><br/>$indent") append("<i> for </i><br/>$indent")
// candidate descriptor is not in context of the rest of the message // candidate descriptor is not in context of the rest of the message
append(descriptorRenderer.render(resolvedCall.candidateDescriptor, RenderingContext.of(resolvedCall.candidateDescriptor))) append(descriptorRenderer.render(resolvedCall.candidateDescriptor, RenderingContext.of(resolvedCall.candidateDescriptor)))
} } else {
else {
append(" <i>defined in</i> ") append(" <i>defined in</i> ")
val containingDeclaration = resultingDescriptor.containingDeclaration val containingDeclaration = resultingDescriptor.containingDeclaration
val fqName = DescriptorUtils.getFqName(containingDeclaration) val fqName = DescriptorUtils.getFqName(containingDeclaration)
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.inspections package org.jetbrains.kotlin.idea.inspections
@@ -43,8 +32,8 @@ import kotlin.reflect.KClass
// thus making the original purpose useless. // thus making the original purpose useless.
// The class still can be used, if you want to create a pair for existing intention with additional checker // The class still can be used, if you want to create a pair for existing intention with additional checker
abstract class IntentionBasedInspection<TElement : PsiElement> private constructor( abstract class IntentionBasedInspection<TElement : PsiElement> private constructor(
private val intentionInfo: IntentionData<TElement>, private val intentionInfo: IntentionData<TElement>,
protected open val problemText: String? protected open val problemText: String?
) : AbstractKotlinInspection() { ) : AbstractKotlinInspection() {
val intention: SelfTargetingRangeIntention<TElement> by lazy { val intention: SelfTargetingRangeIntention<TElement> by lazy {
@@ -57,27 +46,26 @@ abstract class IntentionBasedInspection<TElement : PsiElement> private construct
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
@Deprecated("Please do not use for new inspections. Use AbstractKotlinInspection as base class for them") @Deprecated("Please do not use for new inspections. Use AbstractKotlinInspection as base class for them")
constructor( constructor(
intention: KClass<out SelfTargetingRangeIntention<TElement>>, intention: KClass<out SelfTargetingRangeIntention<TElement>>,
problemText: String? = null problemText: String? = null
) : this(IntentionData(intention), problemText) ) : this(IntentionData(intention), problemText)
constructor( constructor(
intention: KClass<out SelfTargetingRangeIntention<TElement>>, intention: KClass<out SelfTargetingRangeIntention<TElement>>,
additionalChecker: (TElement, IntentionBasedInspection<TElement>) -> Boolean, additionalChecker: (TElement, IntentionBasedInspection<TElement>) -> Boolean,
problemText: String? = null problemText: String? = null
) : this(IntentionData(intention, additionalChecker), problemText) ) : this(IntentionData(intention, additionalChecker), problemText)
constructor( constructor(
intention: KClass<out SelfTargetingRangeIntention<TElement>>, intention: KClass<out SelfTargetingRangeIntention<TElement>>,
additionalChecker: (TElement) -> Boolean, additionalChecker: (TElement) -> Boolean,
problemText: String? = null problemText: String? = null
) : this(IntentionData(intention, { element, _ -> additionalChecker(element) } ), problemText) ) : this(IntentionData(intention) { element, _ -> additionalChecker(element) }, problemText)
data class IntentionData<TElement : PsiElement>( data class IntentionData<TElement : PsiElement>(
val intention: KClass<out SelfTargetingRangeIntention<TElement>>, val intention: KClass<out SelfTargetingRangeIntention<TElement>>,
val additionalChecker: (TElement, IntentionBasedInspection<TElement>) -> Boolean = { _, _ -> true } val additionalChecker: (TElement, IntentionBasedInspection<TElement>) -> Boolean = { _, _ -> true }
) )
open fun additionalFixes(element: TElement): List<LocalQuickFix>? = null open fun additionalFixes(element: TElement): List<LocalQuickFix>? = null
@@ -127,12 +115,12 @@ abstract class IntentionBasedInspection<TElement : PsiElement> private construct
additionalFixes(targetElement)?.let { allFixes.addAll(it) } additionalFixes(targetElement)?.let { allFixes.addAll(it) }
if (!allFixes.isEmpty()) { if (!allFixes.isEmpty()) {
holder.registerProblemWithoutOfflineInformation( holder.registerProblemWithoutOfflineInformation(
targetElement, targetElement,
inspectionProblemText(element) ?: problemText ?: allFixes.first().name, inspectionProblemText(element) ?: problemText ?: allFixes.first().name,
isOnTheFly, isOnTheFly,
problemHighlightType(targetElement), problemHighlightType(targetElement),
range, range,
*allFixes.toTypedArray() *allFixes.toTypedArray()
) )
} }
} }
@@ -141,25 +129,23 @@ abstract class IntentionBasedInspection<TElement : PsiElement> private construct
} }
protected open fun problemHighlightType(element: TElement): ProblemHighlightType = protected open fun problemHighlightType(element: TElement): ProblemHighlightType =
ProblemHighlightType.GENERIC_ERROR_OR_WARNING ProblemHighlightType.GENERIC_ERROR_OR_WARNING
private fun createQuickFix( private fun createQuickFix(
intention: SelfTargetingRangeIntention<TElement>, intention: SelfTargetingRangeIntention<TElement>,
additionalChecker: (TElement, IntentionBasedInspection<TElement>) -> Boolean, additionalChecker: (TElement, IntentionBasedInspection<TElement>) -> Boolean,
targetElement: TElement targetElement: TElement
): IntentionBasedQuickFix { ): IntentionBasedQuickFix = when (intention) {
return when (intention) { is LowPriorityAction -> LowPriorityIntentionBasedQuickFix(intention, additionalChecker, targetElement)
is LowPriorityAction -> LowPriorityIntentionBasedQuickFix(intention, additionalChecker, targetElement) is HighPriorityAction -> HighPriorityIntentionBasedQuickFix(intention, additionalChecker, targetElement)
is HighPriorityAction -> HighPriorityIntentionBasedQuickFix(intention, additionalChecker, targetElement) else -> IntentionBasedQuickFix(intention, additionalChecker, targetElement)
else -> IntentionBasedQuickFix(intention, additionalChecker, targetElement)
}
} }
/* we implement IntentionAction to provide isAvailable which will be used to hide outdated items and make sure we never call 'invoke' for such item */ /* we implement IntentionAction to provide isAvailable which will be used to hide outdated items and make sure we never call 'invoke' for such item */
internal open inner class IntentionBasedQuickFix( internal open inner class IntentionBasedQuickFix(
val intention: SelfTargetingRangeIntention<TElement>, val intention: SelfTargetingRangeIntention<TElement>,
private val additionalChecker: (TElement, IntentionBasedInspection<TElement>) -> Boolean, private val additionalChecker: (TElement, IntentionBasedInspection<TElement>) -> Boolean,
targetElement: TElement targetElement: TElement
) : LocalQuickFixOnPsiElement(targetElement), IntentionAction { ) : LocalQuickFixOnPsiElement(targetElement), IntentionAction {
private val text = intention.text private val text = intention.text
@@ -200,15 +186,15 @@ abstract class IntentionBasedInspection<TElement : PsiElement> private construct
} }
private inner class LowPriorityIntentionBasedQuickFix( private inner class LowPriorityIntentionBasedQuickFix(
intention: SelfTargetingRangeIntention<TElement>, intention: SelfTargetingRangeIntention<TElement>,
additionalChecker: (TElement, IntentionBasedInspection<TElement>) -> Boolean, additionalChecker: (TElement, IntentionBasedInspection<TElement>) -> Boolean,
targetElement: TElement targetElement: TElement
) : IntentionBasedQuickFix(intention, additionalChecker, targetElement), LowPriorityAction ) : IntentionBasedQuickFix(intention, additionalChecker, targetElement), LowPriorityAction
private inner class HighPriorityIntentionBasedQuickFix( private inner class HighPriorityIntentionBasedQuickFix(
intention: SelfTargetingRangeIntention<TElement>, intention: SelfTargetingRangeIntention<TElement>,
additionalChecker: (TElement, IntentionBasedInspection<TElement>) -> Boolean, additionalChecker: (TElement, IntentionBasedInspection<TElement>) -> Boolean,
targetElement: TElement targetElement: TElement
) : IntentionBasedQuickFix(intention, additionalChecker, targetElement), HighPriorityAction ) : IntentionBasedQuickFix(intention, additionalChecker, targetElement), HighPriorityAction
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.intentions package org.jetbrains.kotlin.idea.intentions
@@ -21,7 +10,8 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.* import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.references.ReferenceAccess import org.jetbrains.kotlin.idea.references.ReferenceAccess
import org.jetbrains.kotlin.idea.references.readWriteAccess import org.jetbrains.kotlin.idea.references.readWriteAccess
@@ -89,23 +79,23 @@ class OperatorToFunctionIntention :
private fun isApplicableCall(element: KtCallExpression, caretOffset: Int): Boolean { private fun isApplicableCall(element: KtCallExpression, caretOffset: Int): Boolean {
val lbrace = (element.valueArgumentList?.leftParenthesis val lbrace = (element.valueArgumentList?.leftParenthesis
?: element.lambdaArguments.firstOrNull()?.getLambdaExpression()?.leftCurlyBrace ?: element.lambdaArguments.firstOrNull()?.getLambdaExpression()?.leftCurlyBrace
?: return false) as PsiElement ?: return false) as PsiElement
if (!lbrace.textRange.containsOffset(caretOffset)) return false if (!lbrace.textRange.containsOffset(caretOffset)) return false
val resolvedCall = element.resolveToCall(BodyResolveMode.FULL) val resolvedCall = element.resolveToCall(BodyResolveMode.FULL)
val descriptor = resolvedCall?.resultingDescriptor val descriptor = resolvedCall?.resultingDescriptor
if (descriptor is FunctionDescriptor && descriptor.getName() == OperatorNameConventions.INVOKE) { if (descriptor is FunctionDescriptor && descriptor.getName() == OperatorNameConventions.INVOKE) {
if (element.parent is KtDotQualifiedExpression && if (element.parent is KtDotQualifiedExpression &&
element.calleeExpression?.text == OperatorNameConventions.INVOKE.asString()) return false element.calleeExpression?.text == OperatorNameConventions.INVOKE.asString()
) return false
return element.valueArgumentList != null || element.lambdaArguments.isNotEmpty() return element.valueArgumentList != null || element.lambdaArguments.isNotEmpty()
} }
return false return false
} }
private fun convertUnary(element: KtUnaryExpression): KtExpression { private fun convertUnary(element: KtUnaryExpression): KtExpression {
val op = element.operationReference.getReferencedNameElementType() val operatorName = when (element.operationReference.getReferencedNameElementType()) {
val operatorName = when (op) {
KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> return convertUnaryWithAssignFix(element) KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> return convertUnaryWithAssignFix(element)
KtTokens.PLUS -> OperatorNameConventions.UNARY_PLUS KtTokens.PLUS -> OperatorNameConventions.UNARY_PLUS
KtTokens.MINUS -> OperatorNameConventions.UNARY_MINUS KtTokens.MINUS -> OperatorNameConventions.UNARY_MINUS
@@ -118,8 +108,7 @@ class OperatorToFunctionIntention :
} }
private fun convertUnaryWithAssignFix(element: KtUnaryExpression): KtExpression { private fun convertUnaryWithAssignFix(element: KtUnaryExpression): KtExpression {
val op = element.operationReference.getReferencedNameElementType() val operatorName = when (element.operationReference.getReferencedNameElementType()) {
val operatorName = when (op) {
KtTokens.PLUSPLUS -> OperatorNameConventions.INC KtTokens.PLUSPLUS -> OperatorNameConventions.INC
KtTokens.MINUSMINUS -> OperatorNameConventions.DEC KtTokens.MINUSMINUS -> OperatorNameConventions.DEC
else -> return element else -> return element
@@ -208,7 +197,8 @@ class OperatorToFunctionIntention :
private fun isAssignmentLeftSide(element: KtArrayAccessExpression): Boolean { private fun isAssignmentLeftSide(element: KtArrayAccessExpression): Boolean {
val parent = element.parent val parent = element.parent
return parent is KtBinaryExpression && parent.operationReference.getReferencedNameElementType() == KtTokens.EQ && element == parent.left return parent is KtBinaryExpression &&
parent.operationReference.getReferencedNameElementType() == KtTokens.EQ && element == parent.left
} }
//TODO: don't use creation by plain text //TODO: don't use creation by plain text
@@ -218,8 +208,8 @@ class OperatorToFunctionIntention :
val argumentString = arguments?.text?.removeSurrounding("(", ")") val argumentString = arguments?.text?.removeSurrounding("(", ")")
val funcLitArgs = element.lambdaArguments val funcLitArgs = element.lambdaArguments
val calleeText = callee.text val calleeText = callee.text
val transformation = "$calleeText.${OperatorNameConventions.INVOKE.asString()}" + val transformation =
(if (argumentString == null) "()" else "($argumentString)") "$calleeText.${OperatorNameConventions.INVOKE.asString()}" + (if (argumentString == null) "()" else "($argumentString)")
val transformed = KtPsiFactory(element).createExpression(transformation) val transformed = KtPsiFactory(element).createExpression(transformation)
val callExpression = transformed.getCalleeExpressionIfAny()?.parent as? KtCallExpression val callExpression = transformed.getCalleeExpressionIfAny()?.parent as? KtCallExpression
if (callExpression != null) { if (callExpression != null) {
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.intentions package org.jetbrains.kotlin.idea.intentions
@@ -36,9 +25,9 @@ import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
@Suppress("EqualsOrHashCode") @Suppress("EqualsOrHashCode")
abstract class SelfTargetingIntention<TElement : PsiElement>( abstract class SelfTargetingIntention<TElement : PsiElement>(
val elementType: Class<TElement>, val elementType: Class<TElement>,
private var text: String, private var text: String,
private val familyName: String = text private val familyName: String = text
) : IntentionAction { ) : IntentionAction {
protected val defaultText: String = text protected val defaultText: String = text
@@ -85,8 +74,7 @@ abstract class SelfTargetingIntention<TElement : PsiElement>(
return getTarget(offset, file) return getTarget(offset, file)
} }
protected open fun allowCaretInsideElement(element: PsiElement): Boolean = protected open fun allowCaretInsideElement(element: PsiElement): Boolean = element !is KtBlockExpression
element !is KtBlockExpression
final override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean { final override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean {
if (ApplicationManager.getApplication().isUnitTestMode) { if (ApplicationManager.getApplication().isUnitTestMode) {
@@ -94,8 +82,7 @@ abstract class SelfTargetingIntention<TElement : PsiElement>(
} }
try { try {
return getTarget(editor, file) != null return getTarget(editor, file) != null
} } finally {
finally {
CREATE_BY_PATTERN_MAY_NOT_REFORMAT = false CREATE_BY_PATTERN_MAY_NOT_REFORMAT = false
} }
} }
@@ -126,9 +113,9 @@ abstract class SelfTargetingIntention<TElement : PsiElement>(
} }
abstract class SelfTargetingRangeIntention<TElement : PsiElement>( abstract class SelfTargetingRangeIntention<TElement : PsiElement>(
elementType: Class<TElement>, elementType: Class<TElement>,
text: String, text: String,
familyName: String = text familyName: String = text
) : SelfTargetingIntention<TElement>(elementType, text, familyName) { ) : SelfTargetingIntention<TElement>(elementType, text, familyName) {
abstract fun applicabilityRange(element: TElement): TextRange? abstract fun applicabilityRange(element: TElement): TextRange?
@@ -140,9 +127,9 @@ abstract class SelfTargetingRangeIntention<TElement : PsiElement>(
} }
abstract class SelfTargetingOffsetIndependentIntention<TElement : KtElement>( abstract class SelfTargetingOffsetIndependentIntention<TElement : KtElement>(
elementType: Class<TElement>, elementType: Class<TElement>,
text: String, text: String,
familyName: String = text familyName: String = text
) : SelfTargetingRangeIntention<TElement>(elementType, text, familyName) { ) : SelfTargetingRangeIntention<TElement>(elementType, text, familyName) {
abstract fun isApplicableTo(element: TElement): Boolean abstract fun isApplicableTo(element: TElement): Boolean
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.kdoc package org.jetbrains.kotlin.idea.kdoc
@@ -20,8 +9,8 @@ import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.stubindex.* import org.jetbrains.kotlin.idea.stubindex.*
import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.LookupLocation
@@ -37,7 +26,12 @@ import org.jetbrains.kotlin.utils.Printer
class IdeSampleResolutionService(val project: Project) : SampleResolutionService { class IdeSampleResolutionService(val project: Project) : SampleResolutionService {
override fun resolveSample(context: BindingContext, fromDescriptor: DeclarationDescriptor, resolutionFacade: ResolutionFacade, qualifiedName: List<String>): Collection<DeclarationDescriptor> { override fun resolveSample(
context: BindingContext,
fromDescriptor: DeclarationDescriptor,
resolutionFacade: ResolutionFacade,
qualifiedName: List<String>
): Collection<DeclarationDescriptor> {
val scope = KotlinSourceFilterScope.projectAndLibrariesSources(GlobalSearchScope.projectScope(project), project) val scope = KotlinSourceFilterScope.projectAndLibrariesSources(GlobalSearchScope.projectScope(project), project)
@@ -48,10 +42,9 @@ class IdeSampleResolutionService(val project: Project) : SampleResolutionService
val functions = KotlinFunctionShortNameIndex.getInstance().get(shortName, project, scope).asSequence() val functions = KotlinFunctionShortNameIndex.getInstance().get(shortName, project, scope).asSequence()
val classes = KotlinClassShortNameIndex.getInstance().get(shortName, project, scope).asSequence() val classes = KotlinClassShortNameIndex.getInstance().get(shortName, project, scope).asSequence()
val descriptors = (functions + classes) val descriptors = (functions + classes).filter { it.fqName == targetFqName }
.filter { it.fqName == targetFqName } .map { it.unsafeResolveToDescriptor(BodyResolveMode.PARTIAL) } // TODO Filter out not visible due dependencies config descriptors
.map { it.unsafeResolveToDescriptor(BodyResolveMode.PARTIAL) } // TODO Filter out not visible due dependencies config descriptors .toList()
.toList()
if (descriptors.isNotEmpty()) if (descriptors.isNotEmpty())
return descriptors return descriptors
@@ -63,16 +56,21 @@ class IdeSampleResolutionService(val project: Project) : SampleResolutionService
private fun shouldNotBeCalled(): Nothing = throw UnsupportedOperationException("Synthetic PVD for KDoc link resolution") private fun shouldNotBeCalled(): Nothing = throw UnsupportedOperationException("Synthetic PVD for KDoc link resolution")
private class GlobalSyntheticPackageViewDescriptor(override val fqName: FqName, private val project: Project, private val scope: GlobalSearchScope) : PackageViewDescriptor { private class GlobalSyntheticPackageViewDescriptor(
override val fqName: FqName,
private val project: Project,
private val scope: GlobalSearchScope
) : PackageViewDescriptor {
override fun getContainingDeclaration(): PackageViewDescriptor? = override fun getContainingDeclaration(): PackageViewDescriptor? =
if (fqName.isOneSegmentFQN()) null else GlobalSyntheticPackageViewDescriptor(fqName.parent(), project, scope) if (fqName.isOneSegmentFQN()) null else GlobalSyntheticPackageViewDescriptor(fqName.parent(), project, scope)
override val memberScope: MemberScope = object : MemberScope { override val memberScope: MemberScope = object : MemberScope {
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> = shouldNotBeCalled() override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> = shouldNotBeCalled()
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<SimpleFunctionDescriptor> = shouldNotBeCalled() override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<SimpleFunctionDescriptor> =
shouldNotBeCalled()
override fun getFunctionNames(): Set<Name> = shouldNotBeCalled() override fun getFunctionNames(): Set<Name> = shouldNotBeCalled()
override fun getVariableNames(): Set<Name> = shouldNotBeCalled() override fun getVariableNames(): Set<Name> = shouldNotBeCalled()
@@ -87,33 +85,35 @@ private class GlobalSyntheticPackageViewDescriptor(override val fqName: FqName,
fun getClassesByNameFilter(nameFilter: (Name) -> Boolean) = KotlinFullClassNameIndex.getInstance() fun getClassesByNameFilter(nameFilter: (Name) -> Boolean) = KotlinFullClassNameIndex.getInstance()
.getAllKeys(project) .getAllKeys(project)
.asSequence() .asSequence()
.filter { it.startsWith(fqName.asString()) } .filter { it.startsWith(fqName.asString()) }
.map(::FqName) .map(::FqName)
.filter { it.isChildOf(fqName) } .filter { it.isChildOf(fqName) }
.filter { nameFilter(it.shortName()) } .filter { nameFilter(it.shortName()) }
.flatMap { KotlinFullClassNameIndex.getInstance()[it.asString(), project, scope].asSequence() } .flatMap { KotlinFullClassNameIndex.getInstance()[it.asString(), project, scope].asSequence() }
.map { it.resolveToDescriptorIfAny() } .map { it.resolveToDescriptorIfAny() }
fun getFunctionsByNameFilter(nameFilter: (Name) -> Boolean) = KotlinTopLevelFunctionFqnNameIndex.getInstance() fun getFunctionsByNameFilter(nameFilter: (Name) -> Boolean) = KotlinTopLevelFunctionFqnNameIndex.getInstance()
.getAllKeys(project) .getAllKeys(project)
.asSequence() .asSequence()
.filter { it.startsWith(fqName.asString()) } .filter { it.startsWith(fqName.asString()) }
.map(::FqName) .map(::FqName)
.filter { it.isChildOf(fqName) } .filter { it.isChildOf(fqName) }
.filter { nameFilter(it.shortName()) } .filter { nameFilter(it.shortName()) }
.flatMap { KotlinTopLevelFunctionFqnNameIndex.getInstance()[it.asString(), project, scope].asSequence() } .flatMap { KotlinTopLevelFunctionFqnNameIndex.getInstance()[it.asString(), project, scope].asSequence() }
.map { it.resolveToDescriptorIfAny() as? DeclarationDescriptor } .map { it.resolveToDescriptorIfAny() as? DeclarationDescriptor }
fun getSubpackages(nameFilter: (Name) -> Boolean) = fun getSubpackages(nameFilter: (Name) -> Boolean) = PackageIndexUtil.getSubPackageFqNames(fqName, scope, project, nameFilter)
PackageIndexUtil.getSubPackageFqNames(fqName, scope, project, nameFilter) .map { GlobalSyntheticPackageViewDescriptor(it, project, scope) }
.map { GlobalSyntheticPackageViewDescriptor(it, project, scope) }
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> override fun getContributedDescriptors(
= (getClassesByNameFilter(nameFilter) kindFilter: DescriptorKindFilter,
+ getFunctionsByNameFilter(nameFilter) nameFilter: (Name) -> Boolean
+ getSubpackages(nameFilter)).filterNotNull().toList() ): Collection<DeclarationDescriptor> = (getClassesByNameFilter(nameFilter) +
getFunctionsByNameFilter(nameFilter) +
getSubpackages(nameFilter)
).filterNotNull().toList()
} }
override val module: ModuleDescriptor override val module: ModuleDescriptor
@@ -1,33 +1,22 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.kdoc package org.jetbrains.kotlin.idea.kdoc
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
class KDocUnresolvedReferenceInspection(): AbstractKotlinInspection() { class KDocUnresolvedReferenceInspection() : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor = override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor =
KDocUnresolvedReferenceVisitor(holder) KDocUnresolvedReferenceVisitor(holder)
private class KDocUnresolvedReferenceVisitor(private val holder: ProblemsHolder): PsiElementVisitor() { private class KDocUnresolvedReferenceVisitor(private val holder: ProblemsHolder) : PsiElementVisitor() {
override fun visitElement(element: PsiElement) { override fun visitElement(element: PsiElement) {
if (element is KDocName) { if (element is KDocName) {
val ref = element.mainReference val ref = element.mainReference
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.modules package org.jetbrains.kotlin.idea.modules
@@ -20,18 +9,15 @@ import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaModule import com.intellij.psi.PsiJavaModule
import com.intellij.psi.PsiManager
import com.intellij.psi.impl.light.LightJavaModule import com.intellij.psi.impl.light.LightJavaModule
import org.jetbrains.annotations.NotNull
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
class IdeJavaModuleResolver(private val project: Project) : JavaModuleResolver { class IdeJavaModuleResolver(private val project: Project) : JavaModuleResolver {
private fun findJavaModule(file: VirtualFile): PsiJavaModule? = private fun findJavaModule(file: VirtualFile): PsiJavaModule? = ModuleHighlightUtil2.getModuleDescriptor(file, project)
ModuleHighlightUtil2.getModuleDescriptor(file, project)
override fun checkAccessibility( override fun checkAccessibility(
fileFromOurModule: VirtualFile?, referencedFile: VirtualFile, referencedPackage: FqName? fileFromOurModule: VirtualFile?, referencedFile: VirtualFile, referencedPackage: FqName?
): JavaModuleResolver.AccessError? { ): JavaModuleResolver.AccessError? {
val ourModule = fileFromOurModule?.let(this::findJavaModule) val ourModule = fileFromOurModule?.let(this::findJavaModule)
val theirModule = findJavaModule(referencedFile) val theirModule = findJavaModule(referencedFile)
@@ -64,5 +50,5 @@ class IdeJavaModuleResolver(private val project: Project) : JavaModuleResolver {
// Returns whether or not [source] exports [packageName] to [target] // Returns whether or not [source] exports [packageName] to [target]
private fun exports(source: PsiJavaModule, packageName: String, target: PsiJavaModule): Boolean = private fun exports(source: PsiJavaModule, packageName: String, target: PsiJavaModule): Boolean =
source is LightJavaModule || JavaModuleGraphUtil.exports(source, packageName, target) source is LightJavaModule || JavaModuleGraphUtil.exports(source, packageName, target)
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.project package org.jetbrains.kotlin.idea.project
@@ -20,30 +9,31 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.stubindex.resolve.PluginDeclarationProviderFactory import org.jetbrains.kotlin.idea.stubindex.resolve.PluginDeclarationProviderFactory
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.AbsentDescriptorHandler
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.LocalDescriptorResolver import org.jetbrains.kotlin.resolve.lazy.LocalDescriptorResolver
import org.jetbrains.kotlin.resolve.lazy.AbsentDescriptorHandler
import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
class IdeaLocalDescriptorResolver( class IdeaLocalDescriptorResolver(
private val resolveElementCache: ResolveElementCache, private val resolveElementCache: ResolveElementCache,
private val absentDescriptorHandler: AbsentDescriptorHandler private val absentDescriptorHandler: AbsentDescriptorHandler
) : LocalDescriptorResolver { ) : LocalDescriptorResolver {
override fun resolveLocalDeclaration(declaration: KtDeclaration): DeclarationDescriptor { override fun resolveLocalDeclaration(declaration: KtDeclaration): DeclarationDescriptor {
val context = resolveElementCache.resolveToElements(listOf(declaration), BodyResolveMode.FULL) val context = resolveElementCache.resolveToElements(listOf(declaration), BodyResolveMode.FULL)
return context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration) return context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration) ?: absentDescriptorHandler.diagnoseDescriptorNotFound(
?: absentDescriptorHandler.diagnoseDescriptorNotFound(declaration) declaration
)
} }
} }
class IdeaAbsentDescriptorHandler( class IdeaAbsentDescriptorHandler(
private val declarationProviderFactory: DeclarationProviderFactory private val declarationProviderFactory: DeclarationProviderFactory
) : AbsentDescriptorHandler { ) : AbsentDescriptorHandler {
override fun diagnoseDescriptorNotFound(declaration: KtDeclaration): DeclarationDescriptor { override fun diagnoseDescriptorNotFound(declaration: KtDeclaration): DeclarationDescriptor {
throw NoDescriptorForDeclarationException( throw NoDescriptorForDeclarationException(
declaration, declaration,
(declarationProviderFactory as? PluginDeclarationProviderFactory)?.debugToString() (declarationProviderFactory as? PluginDeclarationProviderFactory)?.debugToString()
) )
} }
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.project package org.jetbrains.kotlin.idea.project
@@ -61,8 +50,8 @@ class ResolveElementCache(
private fun modificationStamp(resolveElement: KtElement): Long? { private fun modificationStamp(resolveElement: KtElement): Long? {
val file = resolveElement.containingFile val file = resolveElement.containingFile
return when { return when {
// for non-physical file we don't get OUT_OF_CODE_BLOCK_MODIFICATION_COUNT increased and must reset // for non-physical file we don't get OUT_OF_CODE_BLOCK_MODIFICATION_COUNT increased and must reset
// data on any modification of the file // data on any modification of the file
!file.isPhysical -> file.modificationStamp !file.isPhysical -> file.modificationStamp
resolveElement is KtDeclaration && KotlinCodeBlockModificationListener.isBlockDeclaration(resolveElement) -> resolveElement.getModificationStamp() resolveElement is KtDeclaration && KotlinCodeBlockModificationListener.isBlockDeclaration(resolveElement) -> resolveElement.getModificationStamp()
@@ -493,7 +482,7 @@ class ResolveElementCache(
if (declaration is KtClass) { if (declaration is KtClass) {
if (modifierList == declaration.primaryConstructorModifierList) { if (modifierList == declaration.primaryConstructorModifierList) {
descriptor = (descriptor as ClassDescriptor).unsubstitutedPrimaryConstructor descriptor = (descriptor as ClassDescriptor).unsubstitutedPrimaryConstructor
?: error("No constructor found: ${declaration.getText()}") ?: error("No constructor found: ${declaration.getText()}")
} }
} }
@@ -641,10 +630,7 @@ class ResolveElementCache(
val classDescriptor = resolveSession.resolveToDescriptor(klass) as ClassDescriptor val classDescriptor = resolveSession.resolveToDescriptor(klass) as ClassDescriptor
val constructorDescriptor = classDescriptor.unsubstitutedPrimaryConstructor val constructorDescriptor = classDescriptor.unsubstitutedPrimaryConstructor
?: error( ?: error("Can't get primary constructor for descriptor '$classDescriptor' in from class '${klass.getElementTextWithContext()}'")
"Can't get primary constructor for descriptor '$classDescriptor' " +
"in from class '${klass.getElementTextWithContext()}'"
)
ForceResolveUtil.forceResolveAllContents(constructorDescriptor) ForceResolveUtil.forceResolveAllContents(constructorDescriptor)
val primaryConstructor = klass.primaryConstructor val primaryConstructor = klass.primaryConstructor
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.quickfix package org.jetbrains.kotlin.idea.quickfix
@@ -26,13 +15,13 @@ abstract class KotlinIntentionActionsFactory {
protected abstract fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> protected abstract fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction>
protected open fun doCreateActionsForAllProblems( protected open fun doCreateActionsForAllProblems(
sameTypeDiagnostics: Collection<Diagnostic>): List<IntentionAction> = emptyList() sameTypeDiagnostics: Collection<Diagnostic>
): List<IntentionAction> = emptyList()
fun createActions(diagnostic: Diagnostic): List<IntentionAction> = fun createActions(diagnostic: Diagnostic): List<IntentionAction> = createActions(listOfNotNull(diagnostic), false)
createActions(listOfNotNull(diagnostic), false)
fun createActionsForAllProblems(sameTypeDiagnostics: Collection<Diagnostic>): List<IntentionAction> = fun createActionsForAllProblems(sameTypeDiagnostics: Collection<Diagnostic>): List<IntentionAction> =
createActions(sameTypeDiagnostics, true) createActions(sameTypeDiagnostics, true)
private fun createActions(sameTypeDiagnostics: Collection<Diagnostic>, createForAll: Boolean): List<IntentionAction> { private fun createActions(sameTypeDiagnostics: Collection<Diagnostic>, createForAll: Boolean): List<IntentionAction> {
if (sameTypeDiagnostics.isEmpty()) return emptyList() if (sameTypeDiagnostics.isEmpty()) return emptyList()
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.quickfix package org.jetbrains.kotlin.idea.quickfix
@@ -25,7 +14,8 @@ import com.intellij.openapi.extensions.Extensions
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
class QuickFixes { class QuickFixes {
private val factories: Multimap<DiagnosticFactory<*>, KotlinIntentionActionsFactory> = HashMultimap.create<DiagnosticFactory<*>, KotlinIntentionActionsFactory>() private val factories: Multimap<DiagnosticFactory<*>, KotlinIntentionActionsFactory> =
HashMultimap.create<DiagnosticFactory<*>, KotlinIntentionActionsFactory>()
private val actions: Multimap<DiagnosticFactory<*>, IntentionAction> = HashMultimap.create<DiagnosticFactory<*>, IntentionAction>() private val actions: Multimap<DiagnosticFactory<*>, IntentionAction> = HashMultimap.create<DiagnosticFactory<*>, IntentionAction>()
init { init {
@@ -99,7 +99,8 @@ private tailrec fun DeclarationDescriptor.additionalClasses(existingClasses: Col
private fun DeclarationDescriptor.collectAllTypes(): Sequence<FqName?> { private fun DeclarationDescriptor.collectAllTypes(): Sequence<FqName?> {
return when (this) { return when (this) {
is ClassConstructorDescriptor -> valueParameters.asSequence().map(ValueParameterDescriptor::getType).flatMap(KotlinType::collectAllTypes) is ClassConstructorDescriptor -> valueParameters.asSequence().map(ValueParameterDescriptor::getType)
.flatMap(KotlinType::collectAllTypes)
is ClassDescriptor -> if (isInline) unsubstitutedPrimaryConstructor?.collectAllTypes().orEmpty() else { is ClassDescriptor -> if (isInline) unsubstitutedPrimaryConstructor?.collectAllTypes().orEmpty() else {
emptySequence() emptySequence()
} + declaredTypeParameters.asSequence().flatMap(DeclarationDescriptor::collectAllTypes) + sequenceOf(fqNameOrNull()) } + declaredTypeParameters.asSequence().flatMap(DeclarationDescriptor::collectAllTypes) + sequenceOf(fqNameOrNull())
@@ -70,8 +70,7 @@ internal class KotlinDefaultAnnotationMethodImplicitReferenceContributor : Kotli
override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) { override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) {
registrar.registerProvider<KtValueArgument> { registrar.registerProvider<KtValueArgument> {
if (it.isNamed()) return@registerProvider null if (it.isNamed()) return@registerProvider null
val annotationEntry = it.getParentOfTypeAndBranch<KtAnnotationEntry> { valueArgumentList } val annotationEntry = it.getParentOfTypeAndBranch<KtAnnotationEntry> { valueArgumentList } ?: return@registerProvider null
?: return@registerProvider null
if (annotationEntry.valueArguments.size != 1) return@registerProvider null if (annotationEntry.valueArguments.size != 1) return@registerProvider null
ReferenceImpl(it) ReferenceImpl(it)
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
@@ -26,7 +15,10 @@ import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.lexer.KtToken import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtQualifiedExpression
import org.jetbrains.kotlin.psi.buildExpression
import org.jetbrains.kotlin.psi.psiUtil.getPossiblyQualifiedCallExpression import org.jetbrains.kotlin.psi.psiUtil.getPossiblyQualifiedCallExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_GET import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_GET
@@ -63,8 +55,7 @@ class KtArrayAccessReference(
appendExpression(arrayExpression.receiverExpression) appendExpression(arrayExpression.receiverExpression)
appendFixedText(arrayExpression.operationSign.value) appendFixedText(arrayExpression.operationSign.value)
appendExpression(arrayExpression.selectorExpression) appendExpression(arrayExpression.selectorExpression)
} } else {
else {
appendExpression(arrayExpression) appendExpression(arrayExpression)
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
@@ -25,11 +14,11 @@ import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver import org.jetbrains.kotlin.resolve.CollectionLiteralResolver
class KtCollectionLiteralReference(expression: KtCollectionLiteralExpression) : KtSimpleReference<KtCollectionLiteralExpression>(expression), MultiRangeReference { class KtCollectionLiteralReference(expression: KtCollectionLiteralExpression) :
KtSimpleReference<KtCollectionLiteralExpression>(expression), MultiRangeReference {
companion object { companion object {
private val COLLECTION_LITERAL_CALL_NAMES = private val COLLECTION_LITERAL_CALL_NAMES =
CollectionLiteralResolver.PRIMITIVE_TYPE_TO_ARRAY.values + CollectionLiteralResolver.PRIMITIVE_TYPE_TO_ARRAY.values + CollectionLiteralResolver.ARRAY_OF_FUNCTION
CollectionLiteralResolver.ARRAY_OF_FUNCTION
} }
override fun getRangeInElement(): TextRange = element.normalizeRange() override fun getRangeInElement(): TextRange = element.normalizeRange()
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
@@ -27,7 +16,8 @@ import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
class KtDestructuringDeclarationReference(element: KtDestructuringDeclarationEntry) : AbstractKtReference<KtDestructuringDeclarationEntry>(element) { class KtDestructuringDeclarationReference(element: KtDestructuringDeclarationEntry) :
AbstractKtReference<KtDestructuringDeclarationEntry>(element) {
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> { override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
return listOfNotNull(context[BindingContext.COMPONENT_RESOLVED_CALL, element]?.candidateDescriptor) return listOfNotNull(context[BindingContext.COMPONENT_RESOLVED_CALL, element]?.candidateDescriptor)
} }
@@ -36,7 +26,9 @@ class KtDestructuringDeclarationReference(element: KtDestructuringDeclarationEnt
override fun canRename(): Boolean { override fun canRename(): Boolean {
val bindingContext = expression.analyze() //TODO: should it use full body resolve? val bindingContext = expression.analyze() //TODO: should it use full body resolve?
return resolveToDescriptors(bindingContext).all { it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED} return resolveToDescriptors(bindingContext).all {
it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
}
} }
override fun handleElementRename(newElementName: String): PsiElement? { override fun handleElementRename(newElementName: String): PsiElement? {
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
@@ -42,15 +31,15 @@ class KtForLoopInReference(element: KtForExpression) : KtMultiReference<KtForExp
companion object { companion object {
private val LOOP_RANGE_KEYS = arrayOf( private val LOOP_RANGE_KEYS = arrayOf(
BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL,
BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL,
BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL
) )
private val NAMES = listOf( private val NAMES = listOf(
OperatorNameConventions.ITERATOR, OperatorNameConventions.ITERATOR,
OperatorNameConventions.NEXT, OperatorNameConventions.NEXT,
OperatorNameConventions.HAS_NEXT OperatorNameConventions.HAS_NEXT
) )
} }
} }
@@ -98,9 +98,11 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere
expression.replace(qualifiedElement.receiverExpression) expression.replace(qualifiedElement.receiverExpression)
qualifiedElement.replaced(qualifiedElement.selectorExpression!!) qualifiedElement.replaced(qualifiedElement.selectorExpression!!)
} }
is KtUserType -> { is KtUserType -> expression.replaced(
expression.replaced(KtPsiFactory(expression).createSimpleName(SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.asString())) KtPsiFactory(expression).createSimpleName(
} SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.asString()
)
)
else -> expression else -> expression
} }
} }
@@ -296,7 +298,9 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere
val importDirective = file.findImportByAlias(name) ?: return null val importDirective = file.findImportByAlias(name) ?: return null
val fqName = importDirective.importedFqName ?: return null val fqName = importDirective.importedFqName ?: return null
val importedDescriptors = file.resolveImportReference(fqName).map { it.unwrap() } val importedDescriptors = file.resolveImportReference(fqName).map { it.unwrap() }
if (getTargetDescriptors(element.analyze(BodyResolveMode.PARTIAL)).any { it.unwrap().getImportableDescriptor() in importedDescriptors }) { if (getTargetDescriptors(element.analyze(BodyResolveMode.PARTIAL)).any {
it.unwrap().getImportableDescriptor() in importedDescriptors
}) {
return importDirective.alias return importDirective.alias
} }
return null return null
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
@@ -38,7 +27,7 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpression, private val getter: Boolean) : sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpression, private val getter: Boolean) :
KtSimpleReference<KtNameReferenceExpression>(expression) { KtSimpleReference<KtNameReferenceExpression>(expression) {
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> { override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
val descriptors = super.getTargetDescriptors(context) val descriptors = super.getTargetDescriptors(context)
if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList() if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList()
@@ -115,10 +104,10 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre
//TODO: it's not correct //TODO: it's not correct
//TODO: setIsY -> setIsIsY bug //TODO: setIsY -> setIsIsY bug
SyntheticJavaPropertyDescriptor.propertyNameBySetMethodName( SyntheticJavaPropertyDescriptor.propertyNameBySetMethodName(
newNameAsName, newNameAsName,
withIsPrefix = expression.getReferencedNameAsName().asString().startsWith( withIsPrefix = expression.getReferencedNameAsName().asString().startsWith(
"is" "is"
) )
) )
} }
// get/set becomes ordinary method // get/set becomes ordinary method
@@ -162,16 +151,16 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre
} else { } else {
val anchor = parent.parentsWithSelf.firstOrNull { it.parent == context } val anchor = parent.parentsWithSelf.firstOrNull { it.parent == context }
val validator = NewDeclarationNameValidator( val validator = NewDeclarationNameValidator(
context, context,
anchor, anchor,
NewDeclarationNameValidator.Target.VARIABLES NewDeclarationNameValidator.Target.VARIABLES
) )
val varName = KotlinNameSuggester.suggestNamesByExpressionAndType( val varName = KotlinNameSuggester.suggestNamesByExpressionAndType(
unaryExpr, unaryExpr,
null, null,
unaryExpr.analyze(), unaryExpr.analyze(),
validator, validator,
"p" "p"
).first() ).first()
val isPrefix = unaryExpr is KtPrefixExpression val isPrefix = unaryExpr is KtPrefixExpression
val varInitializer = if (isPrefix) incDecValue else originalValue val varInitializer = if (isPrefix) incDecValue else originalValue
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
@@ -89,9 +78,12 @@ fun DeclarationDescriptor.findPsiDeclarations(project: Project, resolveScope: Gl
fun Collection<KtNamedDeclaration>.fqNameFilter() = filter { it.fqName == fqName } fun Collection<KtNamedDeclaration>.fqNameFilter() = filter { it.fqName == fqName }
return when (this) { return when (this) {
is DeserializedClassDescriptor -> KotlinFullClassNameIndex.getInstance()[fqName.asString(), project, resolveScope] is DeserializedClassDescriptor -> KotlinFullClassNameIndex.getInstance()[fqName.asString(), project, resolveScope]
is DeserializedTypeAliasDescriptor -> KotlinTypeAliasShortNameIndex.getInstance()[fqName.shortName().asString(), project, resolveScope].fqNameFilter() is DeserializedTypeAliasDescriptor -> KotlinTypeAliasShortNameIndex.getInstance()[fqName.shortName()
is DeserializedSimpleFunctionDescriptor, is FunctionImportedFromObject -> KotlinFunctionShortNameIndex.getInstance()[fqName.shortName().asString(), project, resolveScope].fqNameFilter() .asString(), project, resolveScope].fqNameFilter()
is DeserializedPropertyDescriptor, is PropertyImportedFromObject -> KotlinPropertyShortNameIndex.getInstance()[fqName.shortName().asString(), project, resolveScope].fqNameFilter() is DeserializedSimpleFunctionDescriptor, is FunctionImportedFromObject -> KotlinFunctionShortNameIndex.getInstance()[fqName.shortName()
.asString(), project, resolveScope].fqNameFilter()
is DeserializedPropertyDescriptor, is PropertyImportedFromObject -> KotlinPropertyShortNameIndex.getInstance()[fqName.shortName()
.asString(), project, resolveScope].fqNameFilter()
is DeclarationDescriptorWithSource -> listOfNotNull(source.getPsi()) is DeclarationDescriptorWithSource -> listOfNotNull(source.getPsi())
else -> emptyList() else -> emptyList()
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.search package org.jetbrains.kotlin.idea.search
@@ -48,10 +37,12 @@ import java.util.concurrent.atomic.AtomicInteger
class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName: String) { class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName: String) {
private val targetShortName = targetClassFqName.substringAfterLast('.') private val targetShortName = targetClassFqName.substringAfterLast('.')
private val targetPackage = targetClassFqName.substringBeforeLast('.', "") private val targetPackage = targetClassFqName.substringBeforeLast('.', "")
/** /**
* Qualified names of packages which contain classes with the same short name as the target class. * Qualified names of packages which contain classes with the same short name as the target class.
*/ */
private val conflictingPackages = mutableListOf<String>() private val conflictingPackages = mutableListOf<String>()
/** /**
* Qualified names of packages which contain typealiases with the same short name as the target class * Qualified names of packages which contain typealiases with the same short name as the target class
* (which may or may not resolve to the target class). * (which may or may not resolve to the target class).
@@ -64,8 +55,10 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName:
companion object { companion object {
@get:TestOnly @get:TestOnly
val attempts = AtomicInteger() val attempts = AtomicInteger()
@get:TestOnly @get:TestOnly
val trueHits = AtomicInteger() val trueHits = AtomicInteger()
@get:TestOnly @get:TestOnly
val falseHits = AtomicInteger() val falseHits = AtomicInteger()

Some files were not shown because too many files have changed in this diff Show More