idea: cleanup 'public', property access syntax
This commit is contained in:
@@ -26,31 +26,31 @@ import org.jetbrains.kotlin.psi.KtElement
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
|
||||||
public interface ResolutionFacade {
|
interface ResolutionFacade {
|
||||||
public val project: Project
|
val project: Project
|
||||||
|
|
||||||
public fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext
|
fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext
|
||||||
|
|
||||||
public fun analyzeFullyAndGetResult(elements: Collection<KtElement>): AnalysisResult
|
fun analyzeFullyAndGetResult(elements: Collection<KtElement>): AnalysisResult
|
||||||
|
|
||||||
public fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor
|
fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor
|
||||||
|
|
||||||
public val moduleDescriptor: ModuleDescriptor
|
val moduleDescriptor: ModuleDescriptor
|
||||||
|
|
||||||
// get service for the module this resolution was created for
|
// get service for the module this resolution was created for
|
||||||
public fun <T : Any> getFrontendService(serviceClass: Class<T>): T
|
fun <T : Any> getFrontendService(serviceClass: Class<T>): T
|
||||||
|
|
||||||
public fun <T : Any> getIdeService(serviceClass: Class<T>): T
|
fun <T : Any> getIdeService(serviceClass: Class<T>): T
|
||||||
|
|
||||||
// get service for the module defined by PsiElement/ModuleDescriptor passed as parameter
|
// get service for the module defined by PsiElement/ModuleDescriptor passed as parameter
|
||||||
public fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T
|
fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T
|
||||||
|
|
||||||
public fun <T : Any> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T
|
fun <T : Any> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public 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)
|
||||||
|
|
||||||
public 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)
|
||||||
@@ -39,7 +39,7 @@ import org.jetbrains.kotlin.util.supertypesWithAny
|
|||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||||
|
|
||||||
public sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: DescriptorKindFilter) {
|
sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: DescriptorKindFilter) {
|
||||||
object UNKNOWN : CallType<Nothing?>(DescriptorKindFilter.ALL)
|
object UNKNOWN : CallType<Nothing?>(DescriptorKindFilter.ALL)
|
||||||
|
|
||||||
object DEFAULT : CallType<Nothing?>(DescriptorKindFilter.ALL)
|
object DEFAULT : CallType<Nothing?>(DescriptorKindFilter.ALL)
|
||||||
@@ -93,7 +93,7 @@ public sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: D
|
|||||||
private object NonAnnotationClassifierExclude : DescriptorKindExclude() {
|
private object NonAnnotationClassifierExclude : DescriptorKindExclude() {
|
||||||
override fun excludes(descriptor: DeclarationDescriptor): Boolean {
|
override fun excludes(descriptor: DeclarationDescriptor): Boolean {
|
||||||
if (descriptor !is ClassifierDescriptor) return false
|
if (descriptor !is ClassifierDescriptor) return false
|
||||||
return descriptor !is ClassDescriptor || descriptor.getKind() != ClassKind.ANNOTATION_CLASS
|
return descriptor !is ClassDescriptor || descriptor.kind != ClassKind.ANNOTATION_CLASS
|
||||||
}
|
}
|
||||||
|
|
||||||
override val fullyExcludedDescriptorKinds: Int get() = 0
|
override val fullyExcludedDescriptorKinds: Int get() = 0
|
||||||
@@ -108,7 +108,7 @@ public sealed class CallType<TReceiver : KtElement?>(val descriptorKindFilter: D
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class CallTypeAndReceiver<TReceiver : KtElement?, TCallType : CallType<TReceiver>>(
|
sealed class CallTypeAndReceiver<TReceiver : KtElement?, TCallType : CallType<TReceiver>>(
|
||||||
val callType: TCallType,
|
val callType: TCallType,
|
||||||
val receiver: TReceiver
|
val receiver: TReceiver
|
||||||
) {
|
) {
|
||||||
@@ -127,7 +127,7 @@ public sealed class CallTypeAndReceiver<TReceiver : KtElement?, TCallType : Call
|
|||||||
class ANNOTATION(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.ANNOTATION>(CallType.ANNOTATION, receiver)
|
class ANNOTATION(receiver: KtExpression?) : CallTypeAndReceiver<KtExpression?, CallType.ANNOTATION>(CallType.ANNOTATION, receiver)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
public fun detect(expression: KtSimpleNameExpression): CallTypeAndReceiver<*, *> {
|
fun detect(expression: KtSimpleNameExpression): CallTypeAndReceiver<*, *> {
|
||||||
val parent = expression.parent
|
val parent = expression.parent
|
||||||
if (parent is KtCallableReferenceExpression) {
|
if (parent is KtCallableReferenceExpression) {
|
||||||
return CallTypeAndReceiver.CALLABLE_REFERENCE(parent.typeReference)
|
return CallTypeAndReceiver.CALLABLE_REFERENCE(parent.typeReference)
|
||||||
@@ -205,7 +205,7 @@ public sealed class CallTypeAndReceiver<TReceiver : KtElement?, TCallType : Call
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun CallTypeAndReceiver<*, *>.receiverTypes(
|
fun CallTypeAndReceiver<*, *>.receiverTypes(
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
contextElement: PsiElement,
|
contextElement: PsiElement,
|
||||||
moduleDescriptor: ModuleDescriptor,
|
moduleDescriptor: ModuleDescriptor,
|
||||||
|
|||||||
@@ -28,13 +28,13 @@ import org.jetbrains.kotlin.types.typeUtil.*
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
fun CallableDescriptor.fuzzyReturnType(): FuzzyType? {
|
fun CallableDescriptor.fuzzyReturnType(): FuzzyType? {
|
||||||
val returnType = getReturnType() ?: return null
|
val returnType = returnType ?: return null
|
||||||
return FuzzyType(returnType, getTypeParameters())
|
return FuzzyType(returnType, typeParameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CallableDescriptor.fuzzyExtensionReceiverType(): FuzzyType? {
|
fun CallableDescriptor.fuzzyExtensionReceiverType(): FuzzyType? {
|
||||||
val receiverParameter = getExtensionReceiverParameter()
|
val receiverParameter = extensionReceiverParameter
|
||||||
return if (receiverParameter != null) FuzzyType(receiverParameter.getType(), getTypeParameters()) else null
|
return if (receiverParameter != null) FuzzyType(receiverParameter.type, typeParameters) else null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FuzzyType.makeNotNullable() = FuzzyType(type.makeNotNullable(), freeParameters)
|
fun FuzzyType.makeNotNullable() = FuzzyType(type.makeNotNullable(), freeParameters)
|
||||||
@@ -52,7 +52,7 @@ class FuzzyType(
|
|||||||
val type: KotlinType,
|
val type: KotlinType,
|
||||||
freeParameters: Collection<TypeParameterDescriptor>
|
freeParameters: Collection<TypeParameterDescriptor>
|
||||||
) {
|
) {
|
||||||
public val freeParameters: Set<TypeParameterDescriptor>
|
val freeParameters: Set<TypeParameterDescriptor>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (freeParameters.isNotEmpty()) {
|
if (freeParameters.isNotEmpty()) {
|
||||||
@@ -70,29 +70,29 @@ class FuzzyType(
|
|||||||
override fun hashCode() = type.hashCode()
|
override fun hashCode() = type.hashCode()
|
||||||
|
|
||||||
private fun MutableSet<TypeParameterDescriptor>.addUsedTypeParameters(type: KotlinType) {
|
private fun MutableSet<TypeParameterDescriptor>.addUsedTypeParameters(type: KotlinType) {
|
||||||
val typeParameter = type.getConstructor().getDeclarationDescriptor() as? TypeParameterDescriptor
|
val typeParameter = type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
||||||
if (typeParameter != null && add(typeParameter)) {
|
if (typeParameter != null && add(typeParameter)) {
|
||||||
typeParameter.getLowerBounds().forEach { addUsedTypeParameters(it) }
|
typeParameter.lowerBounds.forEach { addUsedTypeParameters(it) }
|
||||||
typeParameter.getUpperBounds().forEach { addUsedTypeParameters(it) }
|
typeParameter.upperBounds.forEach { addUsedTypeParameters(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
for (argument in type.getArguments()) {
|
for (argument in type.arguments) {
|
||||||
if (!argument.isStarProjection) { // otherwise we can fall into infinite recursion
|
if (!argument.isStarProjection) { // otherwise we can fall into infinite recursion
|
||||||
addUsedTypeParameters(argument.getType())
|
addUsedTypeParameters(argument.type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun checkIsSubtypeOf(otherType: FuzzyType): TypeSubstitutor?
|
fun checkIsSubtypeOf(otherType: FuzzyType): TypeSubstitutor?
|
||||||
= matchedSubstitutor(otherType, MatchKind.IS_SUBTYPE)
|
= matchedSubstitutor(otherType, MatchKind.IS_SUBTYPE)
|
||||||
|
|
||||||
public fun checkIsSuperTypeOf(otherType: FuzzyType): TypeSubstitutor?
|
fun checkIsSuperTypeOf(otherType: FuzzyType): TypeSubstitutor?
|
||||||
= matchedSubstitutor(otherType, MatchKind.IS_SUPERTYPE)
|
= matchedSubstitutor(otherType, MatchKind.IS_SUPERTYPE)
|
||||||
|
|
||||||
public fun checkIsSubtypeOf(otherType: KotlinType): TypeSubstitutor?
|
fun checkIsSubtypeOf(otherType: KotlinType): TypeSubstitutor?
|
||||||
= checkIsSubtypeOf(FuzzyType(otherType, emptyList()))
|
= checkIsSubtypeOf(FuzzyType(otherType, emptyList()))
|
||||||
|
|
||||||
public fun checkIsSuperTypeOf(otherType: KotlinType): TypeSubstitutor?
|
fun checkIsSuperTypeOf(otherType: KotlinType): TypeSubstitutor?
|
||||||
= checkIsSuperTypeOf(FuzzyType(otherType, emptyList()))
|
= checkIsSuperTypeOf(FuzzyType(otherType, emptyList()))
|
||||||
|
|
||||||
private enum class MatchKind {
|
private enum class MatchKind {
|
||||||
@@ -101,8 +101,8 @@ class FuzzyType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun matchedSubstitutor(otherType: FuzzyType, matchKind: MatchKind): TypeSubstitutor? {
|
private fun matchedSubstitutor(otherType: FuzzyType, matchKind: MatchKind): TypeSubstitutor? {
|
||||||
if (type.isError()) return null
|
if (type.isError) return null
|
||||||
if (otherType.type.isError()) return null
|
if (otherType.type.isError) return null
|
||||||
|
|
||||||
fun KotlinType.checkInheritance(otherType: KotlinType): Boolean {
|
fun KotlinType.checkInheritance(otherType: KotlinType): Boolean {
|
||||||
return when (matchKind) {
|
return when (matchKind) {
|
||||||
|
|||||||
@@ -24,12 +24,10 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.isDynamic
|
import org.jetbrains.kotlin.types.isDynamic
|
||||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||||
|
|
||||||
public object IdeDescriptorRenderers {
|
object IdeDescriptorRenderers {
|
||||||
@JvmField
|
@JvmField val APPROXIMATE_FLEXIBLE_TYPES: (KotlinType) -> KotlinType = { approximateFlexibleTypes(it, true) }
|
||||||
public val APPROXIMATE_FLEXIBLE_TYPES: (KotlinType) -> KotlinType = { approximateFlexibleTypes(it, true) }
|
|
||||||
|
|
||||||
@JvmField
|
@JvmField val APPROXIMATE_FLEXIBLE_TYPES_IN_ARGUMENTS: (KotlinType) -> KotlinType = { approximateFlexibleTypes(it, false) }
|
||||||
public val APPROXIMATE_FLEXIBLE_TYPES_IN_ARGUMENTS: (KotlinType) -> KotlinType = { approximateFlexibleTypes(it, false) }
|
|
||||||
|
|
||||||
private fun unwrapAnonymousType(type: KotlinType): KotlinType {
|
private fun unwrapAnonymousType(type: KotlinType): KotlinType {
|
||||||
if (type.isDynamic()) return type
|
if (type.isDynamic()) return type
|
||||||
@@ -55,20 +53,17 @@ public object IdeDescriptorRenderers {
|
|||||||
modifiers = DescriptorRendererModifier.ALL
|
modifiers = DescriptorRendererModifier.ALL
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField val SOURCE_CODE: DescriptorRenderer = BASE.withOptions {
|
||||||
public val SOURCE_CODE: DescriptorRenderer = BASE.withOptions {
|
|
||||||
nameShortness = NameShortness.SOURCE_CODE_QUALIFIED
|
nameShortness = NameShortness.SOURCE_CODE_QUALIFIED
|
||||||
typeNormalizer = { APPROXIMATE_FLEXIBLE_TYPES(unwrapAnonymousType(it)) }
|
typeNormalizer = { APPROXIMATE_FLEXIBLE_TYPES(unwrapAnonymousType(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField val SOURCE_CODE_FOR_TYPE_ARGUMENTS: DescriptorRenderer = BASE.withOptions {
|
||||||
public val SOURCE_CODE_FOR_TYPE_ARGUMENTS: DescriptorRenderer = BASE.withOptions {
|
|
||||||
nameShortness = NameShortness.SOURCE_CODE_QUALIFIED
|
nameShortness = NameShortness.SOURCE_CODE_QUALIFIED
|
||||||
typeNormalizer = { APPROXIMATE_FLEXIBLE_TYPES_IN_ARGUMENTS(unwrapAnonymousType(it)) }
|
typeNormalizer = { APPROXIMATE_FLEXIBLE_TYPES_IN_ARGUMENTS(unwrapAnonymousType(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField val SOURCE_CODE_SHORT_NAMES_IN_TYPES: DescriptorRenderer = BASE.withOptions {
|
||||||
public val SOURCE_CODE_SHORT_NAMES_IN_TYPES: DescriptorRenderer = BASE.withOptions {
|
|
||||||
nameShortness = NameShortness.SHORT
|
nameShortness = NameShortness.SHORT
|
||||||
typeNormalizer = { APPROXIMATE_FLEXIBLE_TYPES(unwrapAnonymousType(it)) }
|
typeNormalizer = { APPROXIMATE_FLEXIBLE_TYPES(unwrapAnonymousType(it)) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,36 +28,36 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
public val DeclarationDescriptor.importableFqName: FqName?
|
val DeclarationDescriptor.importableFqName: FqName?
|
||||||
get() {
|
get() {
|
||||||
if (!canBeReferencedViaImport()) return null
|
if (!canBeReferencedViaImport()) return null
|
||||||
return getImportableDescriptor().fqNameSafe
|
return getImportableDescriptor().fqNameSafe
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun DeclarationDescriptor.canBeReferencedViaImport(): Boolean {
|
fun DeclarationDescriptor.canBeReferencedViaImport(): Boolean {
|
||||||
if (this is PackageViewDescriptor ||
|
if (this is PackageViewDescriptor ||
|
||||||
DescriptorUtils.isTopLevelDeclaration(this) ||
|
DescriptorUtils.isTopLevelDeclaration(this) ||
|
||||||
this is CallableDescriptor && DescriptorUtils.isStaticDeclaration(this)) {
|
this is CallableDescriptor && DescriptorUtils.isStaticDeclaration(this)) {
|
||||||
return !name.isSpecial
|
return !name.isSpecial
|
||||||
}
|
}
|
||||||
|
|
||||||
val parentClass = getContainingDeclaration() as? ClassDescriptor ?: return false
|
val parentClass = containingDeclaration as? ClassDescriptor ?: return false
|
||||||
if (!parentClass.canBeReferencedViaImport()) return false
|
if (!parentClass.canBeReferencedViaImport()) return false
|
||||||
|
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is ConstructorDescriptor -> !parentClass.isInner() // inner class constructors can't be referenced via import
|
is ConstructorDescriptor -> !parentClass.isInner // inner class constructors can't be referenced via import
|
||||||
is ClassDescriptor -> true
|
is ClassDescriptor -> true
|
||||||
else -> parentClass.kind == ClassKind.OBJECT
|
else -> parentClass.kind == ClassKind.OBJECT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KotlinType.canBeReferencedViaImport(): Boolean {
|
fun KotlinType.canBeReferencedViaImport(): Boolean {
|
||||||
val descriptor = getConstructor().getDeclarationDescriptor()
|
val descriptor = constructor.declarationDescriptor
|
||||||
return descriptor != null && descriptor.canBeReferencedViaImport()
|
return descriptor != null && descriptor.canBeReferencedViaImport()
|
||||||
}
|
}
|
||||||
|
|
||||||
// for cases when class qualifier refers companion object treats it like reference to class itself
|
// for cases when class qualifier refers companion object treats it like reference to class itself
|
||||||
public fun KtReferenceExpression.getImportableTargets(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
|
fun KtReferenceExpression.getImportableTargets(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
|
||||||
val targets = bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, this]?.let { listOf(it) }
|
val targets = bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, this]?.let { listOf(it) }
|
||||||
?: getReferenceTargets(bindingContext)
|
?: getReferenceTargets(bindingContext)
|
||||||
return targets.map { it.getImportableDescriptor() }.toSet()
|
return targets.map { it.getImportableDescriptor() }.toSet()
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import org.jetbrains.kotlin.types.TypeUtils
|
|||||||
import org.jetbrains.kotlin.util.descriptorsEqualWithSubstitution
|
import org.jetbrains.kotlin.util.descriptorsEqualWithSubstitution
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public 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,
|
||||||
@@ -72,14 +72,14 @@ public class ShadowedDeclarationsFilter(
|
|||||||
private val psiFactory = KtPsiFactory(resolutionFacade.project)
|
private val psiFactory = KtPsiFactory(resolutionFacade.project)
|
||||||
private val dummyExpressionFactory = DummyExpressionFactory(psiFactory)
|
private val dummyExpressionFactory = DummyExpressionFactory(psiFactory)
|
||||||
|
|
||||||
public fun <TDescriptor : DeclarationDescriptor> filter(declarations: Collection<TDescriptor>): Collection<TDescriptor> {
|
fun <TDescriptor : DeclarationDescriptor> filter(declarations: Collection<TDescriptor>): Collection<TDescriptor> {
|
||||||
return declarations
|
return declarations
|
||||||
.groupBy { signature(it) }
|
.groupBy { signature(it) }
|
||||||
.values
|
.values
|
||||||
.flatMap { group -> filterEqualSignatureGroup(group) }
|
.flatMap { group -> filterEqualSignatureGroup(group) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public 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()
|
||||||
@@ -126,14 +126,14 @@ public class ShadowedDeclarationsFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val isFunction = first is FunctionDescriptor
|
val isFunction = first is FunctionDescriptor
|
||||||
val name = first.getName()
|
val name = first.name
|
||||||
val parameters = (first as CallableDescriptor).getValueParameters()
|
val parameters = (first as CallableDescriptor).valueParameters
|
||||||
|
|
||||||
val dummyArgumentExpressions = dummyExpressionFactory.createDummyExpressions(parameters.size)
|
val dummyArgumentExpressions = dummyExpressionFactory.createDummyExpressions(parameters.size)
|
||||||
|
|
||||||
val bindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for filtering shadowed declarations")
|
val bindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for filtering shadowed declarations")
|
||||||
for ((expression, parameter) in dummyArgumentExpressions.zip(parameters)) {
|
for ((expression, parameter) in dummyArgumentExpressions.zip(parameters)) {
|
||||||
bindingTrace.recordType(expression, parameter.varargElementType ?: parameter.getType())
|
bindingTrace.recordType(expression, parameter.varargElementType ?: parameter.type)
|
||||||
bindingTrace.record(BindingContext.PROCESSED, expression, true)
|
bindingTrace.record(BindingContext.PROCESSED, expression, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ public class ShadowedDeclarationsFilter(
|
|||||||
|
|
||||||
private val argumentName: ValueArgumentName? = if (isNamed()) {
|
private val argumentName: ValueArgumentName? = if (isNamed()) {
|
||||||
object : ValueArgumentName {
|
object : ValueArgumentName {
|
||||||
override val asName = parameters[index].getName()
|
override val asName = parameters[index].name
|
||||||
override val referenceExpression = null
|
override val referenceExpression = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,11 +206,11 @@ public class ShadowedDeclarationsFilter(
|
|||||||
CallChecker.DoNothing, false)
|
CallChecker.DoNothing, false)
|
||||||
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.getResultingCalls().map { it.getResultingDescriptor() }
|
val resultingDescriptors = results.resultingCalls.map { it.resultingDescriptor }
|
||||||
val resultingOriginals = resultingDescriptors.mapTo(HashSet<DeclarationDescriptor>()) { it.getOriginal() }
|
val resultingOriginals = resultingDescriptors.mapTo(HashSet<DeclarationDescriptor>()) { it.original }
|
||||||
val filtered = descriptors.filter { candidateDescriptor ->
|
val filtered = descriptors.filter { candidateDescriptor ->
|
||||||
candidateDescriptor.getOriginal() in resultingOriginals /* optimization */
|
candidateDescriptor.original in resultingOriginals /* optimization */
|
||||||
&& resultingDescriptors.any { descriptorsEqualWithSubstitution(it, candidateDescriptor) }
|
&& resultingDescriptors.any { descriptorsEqualWithSubstitution(it, candidateDescriptor) }
|
||||||
}
|
}
|
||||||
return if (filtered.isNotEmpty()) filtered else descriptors /* something went wrong, none of our declarations among resolve candidates, let's not filter anything */
|
return if (filtered.isNotEmpty()) filtered else descriptors /* something went wrong, none of our declarations among resolve candidates, let's not filter anything */
|
||||||
}
|
}
|
||||||
@@ -230,19 +230,19 @@ public class ShadowedDeclarationsFilter(
|
|||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (other === this) return true
|
if (other === this) return true
|
||||||
if (other !is FunctionSignature) return false
|
if (other !is FunctionSignature) return false
|
||||||
if (function.getName() != other.function.getName()) return false
|
if (function.name != other.function.name) return false
|
||||||
val parameters1 = function.getValueParameters()
|
val parameters1 = function.valueParameters
|
||||||
val parameters2 = other.function.getValueParameters()
|
val parameters2 = other.function.valueParameters
|
||||||
if (parameters1.size != parameters2.size) return false
|
if (parameters1.size != parameters2.size) return false
|
||||||
for (i in parameters1.indices) {
|
for (i in parameters1.indices) {
|
||||||
val p1 = parameters1[i]
|
val p1 = parameters1[i]
|
||||||
val p2 = parameters2[i]
|
val p2 = parameters2[i]
|
||||||
if (p1.varargElementType != p2.varargElementType) return false // both should be vararg or or both not
|
if (p1.varargElementType != p2.varargElementType) return false // both should be vararg or or both not
|
||||||
if (p1.getType() != p2.getType()) return false
|
if (p1.type != p2.type) return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode() = function.getName().hashCode() * 17 + function.getValueParameters().size
|
override fun hashCode() = function.name.hashCode() * 17 + function.valueParameters.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,11 +34,11 @@ import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
|||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
import org.jetbrains.kotlin.types.typeUtil.*
|
||||||
|
|
||||||
public fun approximateFlexibleTypes(jetType: KotlinType, outermost: Boolean = true): KotlinType {
|
fun approximateFlexibleTypes(jetType: KotlinType, outermost: Boolean = true): KotlinType {
|
||||||
if (jetType.isDynamic()) return jetType
|
if (jetType.isDynamic()) return jetType
|
||||||
if (jetType.isFlexible()) {
|
if (jetType.isFlexible()) {
|
||||||
val flexible = jetType.flexibility()
|
val flexible = jetType.flexibility()
|
||||||
val lowerClass = flexible.lowerBound.getConstructor().getDeclarationDescriptor() as? ClassDescriptor?
|
val lowerClass = flexible.lowerBound.constructor.declarationDescriptor as? ClassDescriptor?
|
||||||
val isCollection = lowerClass != null && JavaToKotlinClassMap.INSTANCE.isMutable(lowerClass)
|
val isCollection = lowerClass != null && JavaToKotlinClassMap.INSTANCE.isMutable(lowerClass)
|
||||||
// (Mutable)Collection<T>! -> MutableCollection<T>?
|
// (Mutable)Collection<T>! -> MutableCollection<T>?
|
||||||
// Foo<(Mutable)Collection<T>!>! -> Foo<Collection<T>>?
|
// Foo<(Mutable)Collection<T>!>! -> Foo<Collection<T>>?
|
||||||
@@ -54,46 +54,46 @@ public fun approximateFlexibleTypes(jetType: KotlinType, outermost: Boolean = tr
|
|||||||
|
|
||||||
approximation = if (jetType.isAnnotatedNotNull()) approximation.makeNotNullable() else approximation
|
approximation = if (jetType.isAnnotatedNotNull()) approximation.makeNotNullable() else approximation
|
||||||
|
|
||||||
if (approximation.isMarkedNullable() && !flexible.lowerBound.isMarkedNullable() && TypeUtils.isTypeParameter(approximation) && TypeUtils.hasNullableSuperType(approximation)) {
|
if (approximation.isMarkedNullable && !flexible.lowerBound.isMarkedNullable && TypeUtils.isTypeParameter(approximation) && TypeUtils.hasNullableSuperType(approximation)) {
|
||||||
approximation = approximation.makeNotNullable()
|
approximation = approximation.makeNotNullable()
|
||||||
}
|
}
|
||||||
|
|
||||||
return approximation
|
return approximation
|
||||||
}
|
}
|
||||||
return KotlinTypeImpl.create(
|
return KotlinTypeImpl.create(
|
||||||
jetType.getAnnotations(),
|
jetType.annotations,
|
||||||
jetType.getConstructor(),
|
jetType.constructor,
|
||||||
jetType.isMarkedNullable(),
|
jetType.isMarkedNullable,
|
||||||
jetType.getArguments().map { it.substitute { type -> approximateFlexibleTypes(type, false)} },
|
jetType.arguments.map { it.substitute { type -> approximateFlexibleTypes(type, false)} },
|
||||||
ErrorUtils.createErrorScope("This type is not supposed to be used in member resolution", true)
|
ErrorUtils.createErrorScope("This type is not supposed to be used in member resolution", true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KotlinType.isAnnotatedReadOnly(): Boolean = hasAnnotationMaybeExternal(JETBRAINS_READONLY_ANNOTATION)
|
fun KotlinType.isAnnotatedReadOnly(): Boolean = hasAnnotationMaybeExternal(JETBRAINS_READONLY_ANNOTATION)
|
||||||
public fun KotlinType.isAnnotatedNotNull(): Boolean = hasAnnotationMaybeExternal(JETBRAINS_NOT_NULL_ANNOTATION)
|
fun KotlinType.isAnnotatedNotNull(): Boolean = hasAnnotationMaybeExternal(JETBRAINS_NOT_NULL_ANNOTATION)
|
||||||
public fun KotlinType.isAnnotatedNullable(): Boolean = hasAnnotationMaybeExternal(JETBRAINS_NULLABLE_ANNOTATION)
|
fun KotlinType.isAnnotatedNullable(): Boolean = hasAnnotationMaybeExternal(JETBRAINS_NULLABLE_ANNOTATION)
|
||||||
|
|
||||||
private fun KotlinType.hasAnnotationMaybeExternal(fqName: FqName) = with (getAnnotations()) {
|
private fun KotlinType.hasAnnotationMaybeExternal(fqName: FqName) = with (annotations) {
|
||||||
findAnnotation(fqName) ?: findExternalAnnotation(fqName)
|
findAnnotation(fqName) ?: findExternalAnnotation(fqName)
|
||||||
} != null
|
} != null
|
||||||
|
|
||||||
fun KotlinType.isResolvableInScope(scope: LexicalScope?, checkTypeParameters: Boolean): Boolean {
|
fun KotlinType.isResolvableInScope(scope: LexicalScope?, checkTypeParameters: Boolean): Boolean {
|
||||||
if (canBeReferencedViaImport()) return true
|
if (canBeReferencedViaImport()) return true
|
||||||
|
|
||||||
val descriptor = getConstructor().getDeclarationDescriptor()
|
val descriptor = constructor.declarationDescriptor
|
||||||
if (descriptor == null || descriptor.getName().isSpecial()) return false
|
if (descriptor == null || descriptor.name.isSpecial) return false
|
||||||
if (!checkTypeParameters && descriptor is TypeParameterDescriptor) return true
|
if (!checkTypeParameters && descriptor is TypeParameterDescriptor) return true
|
||||||
|
|
||||||
return scope != null && scope.findClassifier(descriptor.name, NoLookupLocation.FROM_IDE) == descriptor
|
return scope != null && scope.findClassifier(descriptor.name, NoLookupLocation.FROM_IDE) == descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KotlinType.approximateWithResolvableType(scope: LexicalScope?, checkTypeParameters: Boolean): KotlinType {
|
fun KotlinType.approximateWithResolvableType(scope: LexicalScope?, checkTypeParameters: Boolean): KotlinType {
|
||||||
if (isError() || isResolvableInScope(scope, checkTypeParameters)) return this
|
if (isError || isResolvableInScope(scope, checkTypeParameters)) return this
|
||||||
return supertypes().firstOrNull { it.isResolvableInScope(scope, checkTypeParameters) }
|
return supertypes().firstOrNull { it.isResolvableInScope(scope, checkTypeParameters) }
|
||||||
?: builtIns.anyType
|
?: builtIns.anyType
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KotlinType.anonymousObjectSuperTypeOrNull(): KotlinType? {
|
fun KotlinType.anonymousObjectSuperTypeOrNull(): KotlinType? {
|
||||||
val classDescriptor = constructor.declarationDescriptor
|
val classDescriptor = constructor.declarationDescriptor
|
||||||
if (classDescriptor != null && DescriptorUtils.isAnonymousObject(classDescriptor)) {
|
if (classDescriptor != null && DescriptorUtils.isAnonymousObject(classDescriptor)) {
|
||||||
return immediateSupertypes().firstOrNull() ?: classDescriptor.builtIns.anyType
|
return immediateSupertypes().firstOrNull() ?: classDescriptor.builtIns.anyType
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ package org.jetbrains.kotlin.idea.util
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|
||||||
public fun KtFunctionLiteral.findLabelAndCall(): Pair<Name?, KtCallExpression?> {
|
fun KtFunctionLiteral.findLabelAndCall(): Pair<Name?, KtCallExpression?> {
|
||||||
val literalParent = (this.getParent() as KtLambdaExpression).getParent()
|
val literalParent = (this.parent as KtLambdaExpression).parent
|
||||||
|
|
||||||
fun KtValueArgument.callExpression(): KtCallExpression? {
|
fun KtValueArgument.callExpression(): KtCallExpression? {
|
||||||
val parent = getParent()
|
val parent = parent
|
||||||
return (if (parent is KtValueArgumentList) parent else this).getParent() as? KtCallExpression
|
return (if (parent is KtValueArgumentList) parent else this).parent as? KtCallExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
when (literalParent) {
|
when (literalParent) {
|
||||||
@@ -35,7 +35,7 @@ public fun KtFunctionLiteral.findLabelAndCall(): Pair<Name?, KtCallExpression?>
|
|||||||
|
|
||||||
is KtValueArgument -> {
|
is KtValueArgument -> {
|
||||||
val callExpression = literalParent.callExpression()
|
val callExpression = literalParent.callExpression()
|
||||||
val label = (callExpression?.getCalleeExpression() as? KtSimpleNameExpression)?.getReferencedNameAsName()
|
val label = (callExpression?.calleeExpression as? KtSimpleNameExpression)?.getReferencedNameAsName()
|
||||||
return Pair(label, callExpression)
|
return Pair(label, callExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.types.typeUtil.TypeNullability
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import org.jetbrains.kotlin.types.typeUtil.nullability
|
import org.jetbrains.kotlin.types.typeUtil.nullability
|
||||||
|
|
||||||
public fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
||||||
receivers: Collection<ReceiverValue>,
|
receivers: Collection<ReceiverValue>,
|
||||||
context: BindingContext,
|
context: BindingContext,
|
||||||
dataFlowInfo: DataFlowInfo,
|
dataFlowInfo: DataFlowInfo,
|
||||||
@@ -42,7 +42,7 @@ public fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCalla
|
|||||||
containingDeclarationOrModule: DeclarationDescriptor
|
containingDeclarationOrModule: DeclarationDescriptor
|
||||||
): Collection<TCallable> {
|
): Collection<TCallable> {
|
||||||
val sequence = receivers.asSequence().flatMap { substituteExtensionIfCallable(it, callType, context, dataFlowInfo, containingDeclarationOrModule).asSequence() }
|
val sequence = receivers.asSequence().flatMap { substituteExtensionIfCallable(it, callType, context, dataFlowInfo, containingDeclarationOrModule).asSequence() }
|
||||||
if (getTypeParameters().isEmpty()) { // optimization for non-generic callables
|
if (typeParameters.isEmpty()) { // optimization for non-generic callables
|
||||||
return sequence.firstOrNull()?.let { listOf(it) } ?: listOf()
|
return sequence.firstOrNull()?.let { listOf(it) } ?: listOf()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -50,16 +50,16 @@ public fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCalla
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallableWithImplicitReceiver(
|
fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallableWithImplicitReceiver(
|
||||||
scope: LexicalScope,
|
scope: LexicalScope,
|
||||||
context: BindingContext,
|
context: BindingContext,
|
||||||
dataFlowInfo: DataFlowInfo
|
dataFlowInfo: DataFlowInfo
|
||||||
): Collection<TCallable> {
|
): Collection<TCallable> {
|
||||||
val receiverValues = scope.getImplicitReceiversWithInstance().map { it.getValue() }
|
val receiverValues = scope.getImplicitReceiversWithInstance().map { it.value }
|
||||||
return substituteExtensionIfCallable(receiverValues, context, dataFlowInfo, CallType.DEFAULT, scope.ownerDescriptor)
|
return substituteExtensionIfCallable(receiverValues, context, dataFlowInfo, CallType.DEFAULT, scope.ownerDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
||||||
receiver: ReceiverValue,
|
receiver: ReceiverValue,
|
||||||
callType: CallType<*>,
|
callType: CallType<*>,
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
@@ -70,7 +70,7 @@ public fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCalla
|
|||||||
return substituteExtensionIfCallable(types, callType)
|
return substituteExtensionIfCallable(types, callType)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
||||||
receiverTypes: Collection<KotlinType>,
|
receiverTypes: Collection<KotlinType>,
|
||||||
callType: CallType<*>
|
callType: CallType<*>
|
||||||
): Collection<TCallable> {
|
): Collection<TCallable> {
|
||||||
@@ -91,7 +91,7 @@ public fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCalla
|
|||||||
}
|
}
|
||||||
substitutor
|
substitutor
|
||||||
}
|
}
|
||||||
if (getTypeParameters().isEmpty()) { // optimization for non-generic callables
|
if (typeParameters.isEmpty()) { // optimization for non-generic callables
|
||||||
return if (substitutors.any()) listOf(this) else listOf()
|
return if (substitutors.any()) listOf(this) else listOf()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -99,10 +99,10 @@ public fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCalla
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun ReceiverValue?.getThisReceiverOwner(bindingContext: BindingContext): DeclarationDescriptor? {
|
fun ReceiverValue?.getThisReceiverOwner(bindingContext: BindingContext): DeclarationDescriptor? {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is ExpressionReceiver -> {
|
is ExpressionReceiver -> {
|
||||||
val thisRef = (KtPsiUtil.deparenthesize(this.expression) as? KtThisExpression)?.getInstanceReference() ?: return null
|
val thisRef = (KtPsiUtil.deparenthesize(this.expression) as? KtThisExpression)?.instanceReference ?: return null
|
||||||
bindingContext[BindingContext.REFERENCE_TARGET, thisRef]
|
bindingContext[BindingContext.REFERENCE_TARGET, thisRef]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
|
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public fun LexicalScope.getImplicitReceiversWithInstance(): Collection<ReceiverParameterDescriptor>
|
fun LexicalScope.getImplicitReceiversWithInstance(): Collection<ReceiverParameterDescriptor>
|
||||||
= getImplicitReceiversWithInstanceToExpression().keys
|
= getImplicitReceiversWithInstanceToExpression().keys
|
||||||
|
|
||||||
public interface ReceiverExpressionFactory {
|
interface ReceiverExpressionFactory {
|
||||||
public fun createExpression(psiFactory: KtPsiFactory, shortThis: Boolean = true): KtExpression
|
fun createExpression(psiFactory: KtPsiFactory, shortThis: Boolean = true): KtExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun LexicalScope.getImplicitReceiversWithInstanceToExpression(): Map<ReceiverParameterDescriptor, ReceiverExpressionFactory?> {
|
fun LexicalScope.getImplicitReceiversWithInstanceToExpression(): Map<ReceiverParameterDescriptor, ReceiverExpressionFactory?> {
|
||||||
// we use a set to workaround a bug with receiver for companion object present twice in the result of getImplicitReceiversHierarchy()
|
// we use a set to workaround a bug with receiver for companion object present twice in the result of getImplicitReceiversHierarchy()
|
||||||
val receivers = LinkedHashSet(getImplicitReceiversHierarchy())
|
val receivers = LinkedHashSet(getImplicitReceiversHierarchy())
|
||||||
|
|
||||||
@@ -46,19 +46,19 @@ public fun LexicalScope.getImplicitReceiversWithInstanceToExpression(): Map<Rece
|
|||||||
var current: DeclarationDescriptor? = ownerDescriptor
|
var current: DeclarationDescriptor? = ownerDescriptor
|
||||||
while (current != null) {
|
while (current != null) {
|
||||||
if (current is PropertyAccessorDescriptor) {
|
if (current is PropertyAccessorDescriptor) {
|
||||||
current = current.getCorrespondingProperty()
|
current = current.correspondingProperty
|
||||||
}
|
}
|
||||||
outerDeclarationsWithInstance.add(current)
|
outerDeclarationsWithInstance.add(current)
|
||||||
|
|
||||||
val classDescriptor = current as? ClassDescriptor
|
val classDescriptor = current as? ClassDescriptor
|
||||||
if (classDescriptor != null && !classDescriptor.isInner() && !DescriptorUtils.isLocal(classDescriptor)) break
|
if (classDescriptor != null && !classDescriptor.isInner && !DescriptorUtils.isLocal(classDescriptor)) break
|
||||||
|
|
||||||
current = current.getContainingDeclaration()
|
current = current.containingDeclaration
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = LinkedHashMap<ReceiverParameterDescriptor, ReceiverExpressionFactory?>()
|
val result = LinkedHashMap<ReceiverParameterDescriptor, ReceiverExpressionFactory?>()
|
||||||
for ((index, receiver) in receivers.withIndex()) {
|
for ((index, receiver) in receivers.withIndex()) {
|
||||||
val owner = receiver.getContainingDeclaration()
|
val owner = receiver.containingDeclaration
|
||||||
val (expressionText, isImmediateThis) = if (owner in outerDeclarationsWithInstance) {
|
val (expressionText, isImmediateThis) = if (owner in outerDeclarationsWithInstance) {
|
||||||
val thisWithLabel = thisQualifierName(receiver)?.let { "this@${it.render()}" }
|
val thisWithLabel = thisQualifierName(receiver)?.let { "this@${it.render()}" }
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
@@ -66,7 +66,7 @@ public fun LexicalScope.getImplicitReceiversWithInstanceToExpression(): Map<Rece
|
|||||||
else
|
else
|
||||||
thisWithLabel to false
|
thisWithLabel to false
|
||||||
}
|
}
|
||||||
else if (owner is ClassDescriptor && owner.getKind().isSingleton()) {
|
else if (owner is ClassDescriptor && owner.kind.isSingleton) {
|
||||||
IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(owner) to false
|
IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(owner) to false
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -86,9 +86,9 @@ public fun LexicalScope.getImplicitReceiversWithInstanceToExpression(): Map<Rece
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun thisQualifierName(receiver: ReceiverParameterDescriptor): Name? {
|
private fun thisQualifierName(receiver: ReceiverParameterDescriptor): Name? {
|
||||||
val descriptor = receiver.getContainingDeclaration()
|
val descriptor = receiver.containingDeclaration
|
||||||
val name = descriptor.getName()
|
val name = descriptor.name
|
||||||
if (!name.isSpecial()) return name
|
if (!name.isSpecial) return name
|
||||||
|
|
||||||
val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtFunctionLiteral
|
val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as? KtFunctionLiteral
|
||||||
return functionLiteral?.findLabelAndCall()?.first
|
return functionLiteral?.findLabelAndCall()?.first
|
||||||
|
|||||||
@@ -37,27 +37,27 @@ import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.utils.collectVariables
|
import org.jetbrains.kotlin.resolve.scopes.utils.collectVariables
|
||||||
|
|
||||||
|
|
||||||
public fun LexicalScope.getAllAccessibleVariables(name: Name): Collection<VariableDescriptor> {
|
fun LexicalScope.getAllAccessibleVariables(name: Name): Collection<VariableDescriptor> {
|
||||||
return getVariablesFromImplicitReceivers(name) + collectVariables(name, NoLookupLocation.FROM_IDE)
|
return getVariablesFromImplicitReceivers(name) + collectVariables(name, NoLookupLocation.FROM_IDE)
|
||||||
}
|
}
|
||||||
|
|
||||||
public 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 { it.type.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_IDE) } +
|
||||||
collectFunctions(name, NoLookupLocation.FROM_IDE)
|
collectFunctions(name, NoLookupLocation.FROM_IDE)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun LexicalScope.getVariablesFromImplicitReceivers(name: Name): Collection<VariableDescriptor> = getImplicitReceiversWithInstance().flatMap {
|
fun LexicalScope.getVariablesFromImplicitReceivers(name: Name): Collection<VariableDescriptor> = getImplicitReceiversWithInstance().flatMap {
|
||||||
it.type.memberScope.getContributedVariables(name, NoLookupLocation.FROM_IDE)
|
it.type.memberScope.getContributedVariables(name, NoLookupLocation.FROM_IDE)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun LexicalScope.getVariableFromImplicitReceivers(name: Name): VariableDescriptor? {
|
fun LexicalScope.getVariableFromImplicitReceivers(name: Name): VariableDescriptor? {
|
||||||
getImplicitReceiversWithInstance().forEach {
|
getImplicitReceiversWithInstance().forEach {
|
||||||
it.type.memberScope.getContributedVariables(name, NoLookupLocation.FROM_IDE).singleOrNull()?.let { return it }
|
it.type.memberScope.getContributedVariables(name, NoLookupLocation.FROM_IDE).singleOrNull()?.let { return it }
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun PsiElement.getResolutionScope(bindingContext: BindingContext, resolutionFacade: ResolutionFacade/*TODO: get rid of this parameter*/): LexicalScope {
|
fun PsiElement.getResolutionScope(bindingContext: BindingContext, resolutionFacade: ResolutionFacade/*TODO: get rid of this parameter*/): LexicalScope {
|
||||||
for (parent in parentsWithSelf) {
|
for (parent in parentsWithSelf) {
|
||||||
if (parent is KtElement) {
|
if (parent is KtElement) {
|
||||||
val scope = bindingContext[BindingContext.LEXICAL_SCOPE, parent]
|
val scope = bindingContext[BindingContext.LEXICAL_SCOPE, parent]
|
||||||
@@ -67,7 +67,7 @@ public fun PsiElement.getResolutionScope(bindingContext: BindingContext, resolut
|
|||||||
if (parent is KtClassBody) {
|
if (parent is KtClassBody) {
|
||||||
val classDescriptor = bindingContext[BindingContext.CLASS, parent.getParent()] as? ClassDescriptorWithResolutionScopes
|
val classDescriptor = bindingContext[BindingContext.CLASS, parent.getParent()] as? ClassDescriptorWithResolutionScopes
|
||||||
if (classDescriptor != null) {
|
if (classDescriptor != null) {
|
||||||
return classDescriptor.getScopeForMemberDeclarationResolution()
|
return classDescriptor.scopeForMemberDeclarationResolution
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +78,6 @@ public fun PsiElement.getResolutionScope(bindingContext: BindingContext, resolut
|
|||||||
error("Not in KtFile")
|
error("Not in KtFile")
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun ResolutionFacade.getFileResolutionScope(file: KtFile): LexicalScope {
|
fun ResolutionFacade.getFileResolutionScope(file: KtFile): LexicalScope {
|
||||||
return frontendService<FileScopeProvider>().getFileResolutionScope(file)
|
return frontendService<FileScopeProvider>().getFileResolutionScope(file)
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.lazy
|
package org.jetbrains.kotlin.resolve.lazy
|
||||||
|
|
||||||
public enum class BodyResolveMode {
|
enum class BodyResolveMode {
|
||||||
FULL,
|
FULL,
|
||||||
PARTIAL,
|
PARTIAL,
|
||||||
PARTIAL_FOR_COMPLETION
|
PARTIAL_FOR_COMPLETION
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ class PartialBodyResolveFilter(
|
|||||||
assert(!KtPsiUtil.isLocal(declaration)) { "Should never be invoked on local declaration otherwise we may miss some local declarations with type Nothing" }
|
assert(!KtPsiUtil.isLocal(declaration)) { "Should never be invoked on local declaration otherwise we may miss some local declarations with type Nothing" }
|
||||||
|
|
||||||
declaration.forEachDescendantOfType<KtCallableDeclaration> { declaration ->
|
declaration.forEachDescendantOfType<KtCallableDeclaration> { declaration ->
|
||||||
if (declaration.getTypeReference().containsProbablyNothing()) {
|
if (declaration.typeReference.containsProbablyNothing()) {
|
||||||
val name = declaration.getName()
|
val name = declaration.name
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
if (declaration is KtNamedFunction) {
|
if (declaration is KtNamedFunction) {
|
||||||
nothingFunctionNames.add(name)
|
nothingFunctionNames.add(name)
|
||||||
@@ -91,8 +91,8 @@ class PartialBodyResolveFilter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (statement is KtDestructuringDeclaration) {
|
else if (statement is KtDestructuringDeclaration) {
|
||||||
if (statement.getEntries().any {
|
if (statement.entries.any {
|
||||||
val name = it.getName()
|
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)
|
||||||
@@ -164,25 +164,25 @@ class PartialBodyResolveFilter(
|
|||||||
override fun visitPostfixExpression(expression: KtPostfixExpression) {
|
override fun visitPostfixExpression(expression: KtPostfixExpression) {
|
||||||
expression.acceptChildren(this)
|
expression.acceptChildren(this)
|
||||||
|
|
||||||
if (expression.getOperationToken() == KtTokens.EXCLEXCL) {
|
if (expression.operationToken == KtTokens.EXCLEXCL) {
|
||||||
addIfCanBeSmartCast(expression.getBaseExpression() ?: return)
|
addIfCanBeSmartCast(expression.baseExpression ?: return)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBinaryWithTypeRHSExpression(expression: KtBinaryExpressionWithTypeRHS) {
|
override fun visitBinaryWithTypeRHSExpression(expression: KtBinaryExpressionWithTypeRHS) {
|
||||||
expression.acceptChildren(this)
|
expression.acceptChildren(this)
|
||||||
|
|
||||||
if (expression.getOperationReference().getReferencedNameElementType() == KtTokens.AS_KEYWORD) {
|
if (expression.operationReference.getReferencedNameElementType() == KtTokens.AS_KEYWORD) {
|
||||||
addIfCanBeSmartCast(expression.getLeft())
|
addIfCanBeSmartCast(expression.left)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBinaryExpression(expression: KtBinaryExpression) {
|
override fun visitBinaryExpression(expression: KtBinaryExpression) {
|
||||||
expression.acceptChildren(this)
|
expression.acceptChildren(this)
|
||||||
|
|
||||||
if (expression.getOperationToken() == KtTokens.ELVIS) {
|
if (expression.operationToken == KtTokens.ELVIS) {
|
||||||
val left = expression.getLeft()
|
val left = expression.left
|
||||||
val right = expression.getRight()
|
val right = expression.right
|
||||||
if (left != null && right != null) {
|
if (left != null && right != null) {
|
||||||
val smartCastName = left.smartCastExpressionName()
|
val smartCastName = left.smartCastExpressionName()
|
||||||
if (smartCastName != null && filter(smartCastName)) {
|
if (smartCastName != null && filter(smartCastName)) {
|
||||||
@@ -194,9 +194,9 @@ class PartialBodyResolveFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitIfExpression(expression: KtIfExpression) {
|
override fun visitIfExpression(expression: KtIfExpression) {
|
||||||
val condition = expression.getCondition()
|
val condition = expression.condition
|
||||||
val thenBranch = expression.getThen()
|
val thenBranch = expression.then
|
||||||
val elseBranch = expression.getElse()
|
val elseBranch = expression.`else`
|
||||||
|
|
||||||
val (thenSmartCastNames, elseSmartCastNames) = possiblySmartCastInCondition(condition)
|
val (thenSmartCastNames, elseSmartCastNames) = possiblySmartCastInCondition(condition)
|
||||||
|
|
||||||
@@ -239,11 +239,11 @@ class PartialBodyResolveFilter(
|
|||||||
|
|
||||||
override fun visitForExpression(expression: KtForExpression) {
|
override fun visitForExpression(expression: KtForExpression) {
|
||||||
// analyze only the loop-range expression, do not enter the loop body
|
// analyze only the loop-range expression, do not enter the loop body
|
||||||
expression.getLoopRange()?.accept(this)
|
expression.loopRange?.accept(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitWhileExpression(expression: KtWhileExpression) {
|
override fun visitWhileExpression(expression: KtWhileExpression) {
|
||||||
val condition = expression.getCondition()
|
val condition = expression.condition
|
||||||
// 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)
|
||||||
@@ -268,9 +268,9 @@ class PartialBodyResolveFilter(
|
|||||||
val emptyResult = Pair(setOf<SmartCastName>(), setOf<SmartCastName>())
|
val emptyResult = Pair(setOf<SmartCastName>(), setOf<SmartCastName>())
|
||||||
when (condition) {
|
when (condition) {
|
||||||
is KtBinaryExpression -> {
|
is KtBinaryExpression -> {
|
||||||
val operation = condition.getOperationToken()
|
val operation = condition.operationToken
|
||||||
val left = condition.getLeft() ?: return emptyResult
|
val left = condition.left ?: return emptyResult
|
||||||
val right = condition.getRight() ?: return emptyResult
|
val right = condition.right ?: return emptyResult
|
||||||
|
|
||||||
fun smartCastInEq(): Pair<Set<SmartCastName>, Set<SmartCastName>> {
|
fun smartCastInEq(): Pair<Set<SmartCastName>, Set<SmartCastName>> {
|
||||||
if (left.isNullLiteral()) {
|
if (left.isNullLiteral()) {
|
||||||
@@ -307,19 +307,19 @@ class PartialBodyResolveFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
is KtIsExpression -> {
|
is KtIsExpression -> {
|
||||||
val cast = condition.getLeftHandSide().smartCastExpressionName().singletonOrEmptySet()
|
val cast = condition.leftHandSide.smartCastExpressionName().singletonOrEmptySet()
|
||||||
return if (condition.isNegated()) Pair(setOf(), cast) else Pair(cast, setOf())
|
return if (condition.isNegated) Pair(setOf(), cast) else Pair(cast, setOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtPrefixExpression -> {
|
is KtPrefixExpression -> {
|
||||||
if (condition.getOperationToken() == KtTokens.EXCL) {
|
if (condition.operationToken == KtTokens.EXCL) {
|
||||||
val operand = condition.getBaseExpression() ?: return emptyResult
|
val operand = condition.baseExpression ?: return emptyResult
|
||||||
return possiblySmartCastInCondition(operand).swap()
|
return possiblySmartCastInCondition(operand).swap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtParenthesizedExpression -> {
|
is KtParenthesizedExpression -> {
|
||||||
val operand = condition.getExpression() ?: return emptyResult
|
val operand = condition.expression ?: return emptyResult
|
||||||
return possiblySmartCastInCondition(operand)
|
return possiblySmartCastInCondition(operand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -345,10 +345,10 @@ class PartialBodyResolveFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitIfExpression(expression: KtIfExpression) {
|
override fun visitIfExpression(expression: KtIfExpression) {
|
||||||
expression.getCondition()?.accept(this)
|
expression.condition?.accept(this)
|
||||||
|
|
||||||
val thenBranch = expression.getThen()
|
val thenBranch = expression.then
|
||||||
val elseBranch = expression.getElse()
|
val elseBranch = expression.`else`
|
||||||
if (thenBranch != null && elseBranch != null) { // if we have only one branch it makes no sense to search exits in it
|
if (thenBranch != null && elseBranch != null) { // if we have only one branch it makes no sense to search exits in it
|
||||||
val thenExits = collectAlwaysExitPoints(thenBranch)
|
val thenExits = collectAlwaysExitPoints(thenBranch)
|
||||||
if (thenExits.isNotEmpty()) {
|
if (thenExits.isNotEmpty()) {
|
||||||
@@ -362,15 +362,15 @@ class PartialBodyResolveFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitForExpression(loop: KtForExpression) {
|
override fun visitForExpression(loop: KtForExpression) {
|
||||||
loop.getLoopRange()?.accept(this)
|
loop.loopRange?.accept(this)
|
||||||
// do not make sense to search exits inside for as not necessary enter it at all
|
// do not make sense to search exits inside for as not necessary enter it at all
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitWhileExpression(loop: KtWhileExpression) {
|
override fun visitWhileExpression(loop: KtWhileExpression) {
|
||||||
val condition = loop.getCondition() ?: return
|
val condition = loop.condition ?: return
|
||||||
if (condition.isTrueConstant()) {
|
if (condition.isTrueConstant()) {
|
||||||
insideLoopLevel++
|
insideLoopLevel++
|
||||||
loop.getBody()?.accept(this)
|
loop.body?.accept(this)
|
||||||
insideLoopLevel--
|
insideLoopLevel--
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -380,9 +380,9 @@ class PartialBodyResolveFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitDoWhileExpression(loop: KtDoWhileExpression) {
|
override fun visitDoWhileExpression(loop: KtDoWhileExpression) {
|
||||||
loop.getCondition()?.accept(this)
|
loop.condition?.accept(this)
|
||||||
insideLoopLevel++
|
insideLoopLevel++
|
||||||
loop.getBody()?.accept(this)
|
loop.body?.accept(this)
|
||||||
insideLoopLevel--
|
insideLoopLevel--
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,7 +399,7 @@ class PartialBodyResolveFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCallExpression(expression: KtCallExpression) {
|
override fun visitCallExpression(expression: KtCallExpression) {
|
||||||
val name = (expression.getCalleeExpression() as? KtSimpleNameExpression)?.getReferencedName()
|
val name = (expression.calleeExpression as? KtSimpleNameExpression)?.getReferencedName()
|
||||||
if (name != null && name in nothingFunctionNames) {
|
if (name != null && name in nothingFunctionNames) {
|
||||||
result.add(expression)
|
result.add(expression)
|
||||||
}
|
}
|
||||||
@@ -414,9 +414,9 @@ class PartialBodyResolveFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBinaryExpression(expression: KtBinaryExpression) {
|
override fun visitBinaryExpression(expression: KtBinaryExpression) {
|
||||||
if (expression.getOperationToken() == KtTokens.ELVIS) {
|
if (expression.operationToken == KtTokens.ELVIS) {
|
||||||
// do not search exits after "?:"
|
// do not search exits after "?:"
|
||||||
expression.getLeft()?.accept(this)
|
expression.left?.accept(this)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
super.visitBinaryExpression(expression)
|
super.visitBinaryExpression(expression)
|
||||||
@@ -462,9 +462,9 @@ class PartialBodyResolveFilter(
|
|||||||
is KtSimpleNameExpression -> SmartCastName(null, this.getReferencedName())
|
is KtSimpleNameExpression -> SmartCastName(null, this.getReferencedName())
|
||||||
|
|
||||||
is KtQualifiedExpression -> {
|
is KtQualifiedExpression -> {
|
||||||
val selector = getSelectorExpression() as? KtSimpleNameExpression ?: return null
|
val selector = selectorExpression as? KtSimpleNameExpression ?: return null
|
||||||
val selectorName = selector.getReferencedName()
|
val selectorName = selector.getReferencedName()
|
||||||
val receiver = getReceiverExpression()
|
val receiver = receiverExpression
|
||||||
if (receiver is KtThisExpression) {
|
if (receiver is KtThisExpression) {
|
||||||
return SmartCastName(null, selectorName)
|
return SmartCastName(null, selectorName)
|
||||||
}
|
}
|
||||||
@@ -518,7 +518,7 @@ class PartialBodyResolveFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
public fun findStatementToResolve(element: KtElement, declaration: KtDeclaration): KtExpression? {
|
fun findStatementToResolve(element: KtElement, declaration: KtDeclaration): KtExpression? {
|
||||||
return element.parentsWithSelf.takeWhile { it != declaration }.firstOrNull { it.isStatement() } as KtExpression?
|
return element.parentsWithSelf.takeWhile { it != declaration }.firstOrNull { it.isStatement() } as KtExpression?
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,16 +526,16 @@ class PartialBodyResolveFilter(
|
|||||||
forEachDescendantOfType(canGoInside = { it !is KtBlockExpression }, action = action)
|
forEachDescendantOfType(canGoInside = { it !is KtBlockExpression }, action = action)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtExpression?.isNullLiteral() = this?.getNode()?.getElementType() == KtNodeTypes.NULL
|
private fun KtExpression?.isNullLiteral() = this?.node?.elementType == KtNodeTypes.NULL
|
||||||
|
|
||||||
private fun KtExpression?.isTrueConstant()
|
private fun KtExpression?.isTrueConstant()
|
||||||
= this != null && getNode()?.getElementType() == KtNodeTypes.BOOLEAN_CONSTANT && getText() == "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 {
|
||||||
val parent = expression.getParent()
|
val parent = expression.parent
|
||||||
return when (parent) {
|
return when (parent) {
|
||||||
is KtBlockExpression -> expression == parent.lastStatement() && isValueNeeded(parent)
|
is KtBlockExpression -> expression == parent.lastStatement() && isValueNeeded(parent)
|
||||||
|
|
||||||
@@ -545,7 +545,7 @@ class PartialBodyResolveFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
is KtDeclarationWithBody -> {
|
is KtDeclarationWithBody -> {
|
||||||
if (expression == parent.getBodyExpression())
|
if (expression == parent.bodyExpression)
|
||||||
!parent.hasBlockBody() && !parent.hasDeclaredReturnType()
|
!parent.hasBlockBody() && !parent.hasDeclaredReturnType()
|
||||||
else
|
else
|
||||||
true
|
true
|
||||||
@@ -558,7 +558,7 @@ class PartialBodyResolveFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun KtBlockExpression.lastStatement(): KtExpression?
|
private fun KtBlockExpression.lastStatement(): KtExpression?
|
||||||
= getLastChild()?.siblings(forward = false)?.firstIsInstanceOrNull<KtExpression>()
|
= lastChild?.siblings(forward = false)?.firstIsInstanceOrNull<KtExpression>()
|
||||||
|
|
||||||
private fun PsiElement.isStatement() = this is KtExpression && getParent() is KtBlockExpression
|
private fun PsiElement.isStatement() = this is KtExpression && getParent() is KtBlockExpression
|
||||||
|
|
||||||
@@ -576,7 +576,7 @@ class PartialBodyResolveFilter(
|
|||||||
if (e.isStatement()) {
|
if (e.isStatement()) {
|
||||||
markStatement(e as KtExpression, level)
|
markStatement(e as KtExpression, level)
|
||||||
}
|
}
|
||||||
e = e.getParent()!!
|
e = e.parent!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,7 +585,7 @@ class PartialBodyResolveFilter(
|
|||||||
if (currentLevel < level) {
|
if (currentLevel < level) {
|
||||||
statementMarks[statement] = level
|
statementMarks[statement] = level
|
||||||
|
|
||||||
val block = statement.getParent() as KtBlockExpression
|
val block = statement.parent as KtBlockExpression
|
||||||
val currentBlockLevel = blockLevels[block] ?: MarkLevel.NONE
|
val currentBlockLevel = blockLevels[block] ?: MarkLevel.NONE
|
||||||
if (currentBlockLevel < level) {
|
if (currentBlockLevel < level) {
|
||||||
blockLevels[block] = level
|
blockLevels[block] = level
|
||||||
@@ -602,7 +602,7 @@ class PartialBodyResolveFilter(
|
|||||||
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.getLastChild().siblings(forward = false)
|
return block.lastChild.siblings(forward = false)
|
||||||
.filterIsInstance<KtExpression>()
|
.filterIsInstance<KtExpression>()
|
||||||
.first { statementMark(it) >= minLevel }
|
.first { statementMark(it) >= minLevel }
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.lazy
|
package org.jetbrains.kotlin.resolve.lazy
|
||||||
|
|
||||||
public interface ProbablyNothingCallableNames {
|
interface ProbablyNothingCallableNames {
|
||||||
public fun functionNames(): Collection<String>
|
fun functionNames(): Collection<String>
|
||||||
public fun propertyNames(): Collection<String>
|
fun propertyNames(): Collection<String>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,23 +22,23 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.utils.Printer
|
import org.jetbrains.kotlin.utils.Printer
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
|
|
||||||
public 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.getName() == name }.firstIsInstanceOrNull<ClassifierDescriptor>()
|
= descriptors.filter { it.name == name }.firstIsInstanceOrNull<ClassifierDescriptor>()
|
||||||
|
|
||||||
override fun getContributedPackage(name: Name)
|
override fun getContributedPackage(name: Name)
|
||||||
= descriptors.filter { it.getName() == 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.getName() == 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.getName() == name }.filterIsInstance<FunctionDescriptor>()
|
= descriptors.filter { it.name == name }.filterIsInstance<FunctionDescriptor>()
|
||||||
|
|
||||||
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
|
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
|
||||||
= descriptors
|
= descriptors
|
||||||
|
|
||||||
override fun printStructure(p: Printer) {
|
override fun printStructure(p: Printer) {
|
||||||
p.println(javaClass.getName())
|
p.println(javaClass.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,15 +25,15 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||||
import org.jetbrains.kotlin.psi.KtUserType
|
import org.jetbrains.kotlin.psi.KtUserType
|
||||||
|
|
||||||
public fun KtUserType.aliasImportMap(): Multimap<String, String> {
|
fun KtUserType.aliasImportMap(): Multimap<String, String> {
|
||||||
// we need to access containing file via stub because getPsi() may return null when indexing and getContainingFile() will crash
|
// we need to access containing file via stub because getPsi() may return null when indexing and getContainingFile() will crash
|
||||||
val file = getStub()?.getContainingFileStub()?.getPsi() ?: return HashMultimap.create()
|
val file = stub?.getContainingFileStub()?.psi ?: return HashMultimap.create()
|
||||||
return (file as KtFile).aliasImportMap()
|
return (file as KtFile).aliasImportMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtFile.aliasImportMap(): Multimap<String, String> {
|
private fun KtFile.aliasImportMap(): Multimap<String, String> {
|
||||||
val cached = getUserData(ALIAS_IMPORT_DATA_KEY)
|
val cached = getUserData(ALIAS_IMPORT_DATA_KEY)
|
||||||
val modificationStamp = getModificationStamp()
|
val modificationStamp = modificationStamp
|
||||||
if (cached != null && modificationStamp == cached.fileModificationStamp) {
|
if (cached != null && modificationStamp == cached.fileModificationStamp) {
|
||||||
return cached.map
|
return cached.map
|
||||||
}
|
}
|
||||||
@@ -45,10 +45,10 @@ private fun KtFile.aliasImportMap(): Multimap<String, String> {
|
|||||||
|
|
||||||
private fun KtFile.buildAliasImportMap(): Multimap<String, String> {
|
private fun KtFile.buildAliasImportMap(): Multimap<String, String> {
|
||||||
val map = HashMultimap.create<String, String>()
|
val map = HashMultimap.create<String, String>()
|
||||||
val importList = getImportList() ?: return map
|
val importList = importList ?: return map
|
||||||
for (import in importList.getImports()) {
|
for (import in importList.imports) {
|
||||||
val aliasName = import.getAliasName() ?: continue
|
val aliasName = import.aliasName ?: continue
|
||||||
val name = import.getImportPath()?.fqnPart()?.shortName()?.asString() ?: continue
|
val name = import.importPath?.fqnPart()?.shortName()?.asString() ?: continue
|
||||||
map.put(aliasName, name)
|
map.put(aliasName, name)
|
||||||
}
|
}
|
||||||
return map
|
return map
|
||||||
@@ -58,14 +58,14 @@ private class CachedAliasImportData(val map: Multimap<String, String>, val fileM
|
|||||||
|
|
||||||
private val ALIAS_IMPORT_DATA_KEY = Key<CachedAliasImportData>("ALIAS_IMPORT_MAP_KEY")
|
private val ALIAS_IMPORT_DATA_KEY = Key<CachedAliasImportData>("ALIAS_IMPORT_MAP_KEY")
|
||||||
|
|
||||||
public fun KtTypeReference?.isProbablyNothing(): Boolean {
|
fun KtTypeReference?.isProbablyNothing(): Boolean {
|
||||||
val userType = this?.typeElement as? KtUserType ?: return false
|
val userType = this?.typeElement as? KtUserType ?: return false
|
||||||
return userType.isProbablyNothing()
|
return userType.isProbablyNothing()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KtUserType?.isProbablyNothing(): Boolean {
|
fun KtUserType?.isProbablyNothing(): Boolean {
|
||||||
if (this == null) return false
|
if (this == null) return false
|
||||||
val referencedName = getReferencedName()
|
val referencedName = referencedName
|
||||||
return referencedName == "Nothing" || aliasImportMap()[referencedName].contains("Nothing")
|
return referencedName == "Nothing" || aliasImportMap()[referencedName].contains("Nothing")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,5 +73,5 @@ private fun StubElement<*>.getContainingFileStub(): PsiFileStub<*> {
|
|||||||
return if (this is PsiFileStub)
|
return if (this is PsiFileStub)
|
||||||
this
|
this
|
||||||
else
|
else
|
||||||
getParentStub().getContainingFileStub()
|
parentStub.getContainingFileStub()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,51 +25,51 @@ import org.jetbrains.kotlin.types.TypeConstructor
|
|||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.typeUtil.equalTypesOrNulls
|
import org.jetbrains.kotlin.types.typeUtil.equalTypesOrNulls
|
||||||
|
|
||||||
public fun descriptorsEqualWithSubstitution(descriptor1: DeclarationDescriptor?, descriptor2: DeclarationDescriptor?): Boolean {
|
fun descriptorsEqualWithSubstitution(descriptor1: DeclarationDescriptor?, descriptor2: DeclarationDescriptor?): 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
|
||||||
if (descriptor1.getOriginal() != descriptor2.getOriginal()) return false
|
if (descriptor1.original != descriptor2.original) return false
|
||||||
if (descriptor1 !is CallableDescriptor) return true
|
if (descriptor1 !is CallableDescriptor) return true
|
||||||
descriptor2 as CallableDescriptor
|
descriptor2 as CallableDescriptor
|
||||||
|
|
||||||
val typeChecker = KotlinTypeChecker.withAxioms(object: KotlinTypeChecker.TypeConstructorEquality {
|
val typeChecker = KotlinTypeChecker.withAxioms(object: KotlinTypeChecker.TypeConstructorEquality {
|
||||||
override fun equals(a: TypeConstructor, b: TypeConstructor): Boolean {
|
override fun equals(a: TypeConstructor, b: TypeConstructor): Boolean {
|
||||||
val typeParam1 = a.getDeclarationDescriptor() as? TypeParameterDescriptor
|
val typeParam1 = a.declarationDescriptor as? TypeParameterDescriptor
|
||||||
val typeParam2 = b.getDeclarationDescriptor() as? TypeParameterDescriptor
|
val typeParam2 = b.declarationDescriptor as? TypeParameterDescriptor
|
||||||
if (typeParam1 != null
|
if (typeParam1 != null
|
||||||
&& typeParam2 != null
|
&& typeParam2 != null
|
||||||
&& typeParam1.getContainingDeclaration() == descriptor1
|
&& typeParam1.containingDeclaration == descriptor1
|
||||||
&& typeParam2.getContainingDeclaration() == descriptor2) {
|
&& typeParam2.containingDeclaration == descriptor2) {
|
||||||
return typeParam1.getIndex() == typeParam2.getIndex()
|
return typeParam1.index == typeParam2.index
|
||||||
}
|
}
|
||||||
|
|
||||||
return a == b
|
return a == b
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!typeChecker.equalTypesOrNulls(descriptor1.getReturnType(), descriptor2.getReturnType())) return false
|
if (!typeChecker.equalTypesOrNulls(descriptor1.returnType, descriptor2.returnType)) return false
|
||||||
|
|
||||||
val parameters1 = descriptor1.getValueParameters()
|
val parameters1 = descriptor1.valueParameters
|
||||||
val parameters2 = descriptor2.getValueParameters()
|
val parameters2 = descriptor2.valueParameters
|
||||||
if (parameters1.size != parameters2.size) return false
|
if (parameters1.size != parameters2.size) return false
|
||||||
for ((param1, param2) in parameters1.zip(parameters2)) {
|
for ((param1, param2) in parameters1.zip(parameters2)) {
|
||||||
if (!typeChecker.equalTypes(param1.getType(), param2.getType())) return false
|
if (!typeChecker.equalTypes(param1.type, param2.type)) return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun ClassDescriptor.findCallableMemberBySignature(signature: CallableMemberDescriptor): CallableMemberDescriptor? {
|
fun ClassDescriptor.findCallableMemberBySignature(signature: 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 getDefaultType().getMemberScope()
|
return defaultType.memberScope
|
||||||
.getContributedDescriptors(descriptorKind)
|
.getContributedDescriptors(descriptorKind)
|
||||||
.filterIsInstance<CallableMemberDescriptor>()
|
.filterIsInstance<CallableMemberDescriptor>()
|
||||||
.firstOrNull {
|
.firstOrNull {
|
||||||
it.getContainingDeclaration() == this
|
it.containingDeclaration == this
|
||||||
&& OverridingUtil.DEFAULT.isOverridableBy(it as CallableDescriptor, signature, null).getResult() == OVERRIDABLE
|
&& OverridingUtil.DEFAULT.isOverridableBy(it as CallableDescriptor, signature, null).result == OVERRIDABLE
|
||||||
} as? CallableMemberDescriptor
|
} as? CallableMemberDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
public 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 }
|
.map { it.constructor.declarationDescriptor as? ClassDescriptor }
|
||||||
|
|||||||
@@ -22,39 +22,39 @@ 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.LinkedHashMap
|
||||||
|
|
||||||
public 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
|
||||||
|
|
||||||
val substitution = LinkedHashMap<TypeConstructor, TypeProjection>(substitutedType.getArguments().size)
|
val substitution = LinkedHashMap<TypeConstructor, TypeProjection>(substitutedType.arguments.size)
|
||||||
for ((param, arg) in baseType.getConstructor().getParameters().zip(substitutedType.getArguments())) {
|
for ((param, arg) in baseType.constructor.parameters.zip(substitutedType.arguments)) {
|
||||||
substitution[param.getTypeConstructor()] = arg
|
substitution[param.typeConstructor] = arg
|
||||||
}
|
}
|
||||||
|
|
||||||
return substitution
|
return substitution
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getCallableSubstitution(
|
fun getCallableSubstitution(
|
||||||
baseCallable: CallableDescriptor,
|
baseCallable: CallableDescriptor,
|
||||||
derivedCallable: CallableDescriptor
|
derivedCallable: CallableDescriptor
|
||||||
): MutableMap<TypeConstructor, TypeProjection>? {
|
): MutableMap<TypeConstructor, TypeProjection>? {
|
||||||
val baseClass = baseCallable.getContainingDeclaration() as? ClassDescriptor ?: return null
|
val baseClass = baseCallable.containingDeclaration as? ClassDescriptor ?: return null
|
||||||
val derivedClass = derivedCallable.getContainingDeclaration() as? ClassDescriptor ?: return null
|
val derivedClass = derivedCallable.containingDeclaration as? ClassDescriptor ?: return null
|
||||||
val substitution = getTypeSubstitution(baseClass.getDefaultType(), derivedClass.getDefaultType()) ?: return null
|
val substitution = getTypeSubstitution(baseClass.defaultType, derivedClass.defaultType) ?: return null
|
||||||
|
|
||||||
for ((baseParam, derivedParam) in baseCallable.getTypeParameters().zip(derivedCallable.getTypeParameters())) {
|
for ((baseParam, derivedParam) in baseCallable.typeParameters.zip(derivedCallable.typeParameters)) {
|
||||||
substitution[baseParam.getTypeConstructor()] = TypeProjectionImpl(derivedParam.getDefaultType())
|
substitution[baseParam.typeConstructor] = TypeProjectionImpl(derivedParam.defaultType)
|
||||||
}
|
}
|
||||||
|
|
||||||
return substitution
|
return substitution
|
||||||
}
|
}
|
||||||
|
|
||||||
public 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) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getTypeSubstitutor(baseType: KotlinType, derivedType: KotlinType): TypeSubstitutor? {
|
fun getTypeSubstitutor(baseType: KotlinType, derivedType: KotlinType): TypeSubstitutor? {
|
||||||
return getTypeSubstitution(baseType, derivedType)?.let { TypeSubstitutor.create(it) }
|
return getTypeSubstitution(baseType, derivedType)?.let { TypeSubstitutor.create(it) }
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -18,11 +18,11 @@ package org.jetbrains.kotlin.idea.actions.internal
|
|||||||
|
|
||||||
import com.intellij.ide.util.PropertiesComponent
|
import com.intellij.ide.util.PropertiesComponent
|
||||||
|
|
||||||
public class KotlinInternalMode {
|
class KotlinInternalMode {
|
||||||
public companion object Instance {
|
companion object Instance {
|
||||||
val INTERNAL_MODE_PROPERTY = "kotlin.internal.mode.enabled"
|
val INTERNAL_MODE_PROPERTY = "kotlin.internal.mode.enabled"
|
||||||
|
|
||||||
public var enabled: Boolean
|
var enabled: Boolean
|
||||||
get() = PropertiesComponent.getInstance()!!.getBoolean(
|
get() = PropertiesComponent.getInstance()!!.getBoolean(
|
||||||
INTERNAL_MODE_PROPERTY,
|
INTERNAL_MODE_PROPERTY,
|
||||||
System.getProperty(INTERNAL_MODE_PROPERTY) == "true"
|
System.getProperty(INTERNAL_MODE_PROPERTY) == "true"
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ 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
|
@JvmOverloads fun KtExpression.computeTypeInfoInContext(
|
||||||
public fun KtExpression.computeTypeInfoInContext(
|
|
||||||
scope: LexicalScope,
|
scope: LexicalScope,
|
||||||
contextExpression: KtExpression = this,
|
contextExpression: KtExpression = this,
|
||||||
trace: BindingTrace = BindingTraceContext(),
|
trace: BindingTrace = BindingTraceContext(),
|
||||||
@@ -44,8 +43,7 @@ public fun KtExpression.computeTypeInfoInContext(
|
|||||||
.getTypeInfo(scope, this, expectedType, dataFlowInfo, trace, isStatement)
|
.getTypeInfo(scope, this, expectedType, dataFlowInfo, trace, isStatement)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads fun KtExpression.analyzeInContext(
|
||||||
public fun KtExpression.analyzeInContext(
|
|
||||||
scope: LexicalScope,
|
scope: LexicalScope,
|
||||||
contextExpression: KtExpression = this,
|
contextExpression: KtExpression = this,
|
||||||
trace: BindingTrace = BindingTraceContext(),
|
trace: BindingTrace = BindingTraceContext(),
|
||||||
@@ -54,11 +52,10 @@ public fun KtExpression.analyzeInContext(
|
|||||||
isStatement: Boolean = false
|
isStatement: Boolean = false
|
||||||
): BindingContext {
|
): BindingContext {
|
||||||
computeTypeInfoInContext(scope, contextExpression, trace, dataFlowInfo, expectedType, isStatement)
|
computeTypeInfoInContext(scope, contextExpression, trace, dataFlowInfo, expectedType, isStatement)
|
||||||
return trace.getBindingContext()
|
return trace.bindingContext
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads fun KtExpression.computeTypeInContext(
|
||||||
public fun KtExpression.computeTypeInContext(
|
|
||||||
scope: LexicalScope,
|
scope: LexicalScope,
|
||||||
contextExpression: KtExpression = this,
|
contextExpression: KtExpression = this,
|
||||||
trace: BindingTrace = BindingTraceContext(),
|
trace: BindingTrace = BindingTraceContext(),
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.idea.caches
|
|||||||
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
|
||||||
public data class CachedAttributeData<T: Enum<T>>(val value: T?, val timeStamp: Long)
|
data class CachedAttributeData<T: Enum<T>>(val value: T?, val timeStamp: Long)
|
||||||
|
|
||||||
interface FileAttributeService {
|
interface FileAttributeService {
|
||||||
fun register(id: String, version: Int) {}
|
fun register(id: String, version: Int) {}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import com.intellij.util.io.URLUtil
|
|||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
public object JarUserDataManager {
|
object JarUserDataManager {
|
||||||
enum class State {
|
enum class State {
|
||||||
INIT,
|
INIT,
|
||||||
HAS_FILE,
|
HAS_FILE,
|
||||||
@@ -37,11 +37,11 @@ public object JarUserDataManager {
|
|||||||
|
|
||||||
val fileAttributeService: FileAttributeService? = ServiceManager.getService(FileAttributeService::class.java)
|
val fileAttributeService: FileAttributeService? = ServiceManager.getService(FileAttributeService::class.java)
|
||||||
|
|
||||||
public fun register(counter: JarBooleanPropertyCounter) {
|
fun register(counter: JarBooleanPropertyCounter) {
|
||||||
fileAttributeService?.register(counter.key.toString(), version)
|
fileAttributeService?.register(counter.key.toString(), version)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun hasFileWithProperty(counter: JarBooleanPropertyCounter, file: VirtualFile): Boolean? {
|
fun hasFileWithProperty(counter: JarBooleanPropertyCounter, file: VirtualFile): Boolean? {
|
||||||
val localJarFile = JarFileSystemUtil.findLocalJarFile(file) ?: return null
|
val localJarFile = JarFileSystemUtil.findLocalJarFile(file) ?: return null
|
||||||
|
|
||||||
val stored = localJarFile.getUserData(counter.key)
|
val stored = localJarFile.getUserData(counter.key)
|
||||||
@@ -108,19 +108,19 @@ public object JarUserDataManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object JarFileSystemUtil {
|
object JarFileSystemUtil {
|
||||||
public fun findJarFileRoot(inJarFile: VirtualFile): VirtualFile? {
|
fun findJarFileRoot(inJarFile: VirtualFile): VirtualFile? {
|
||||||
if (!inJarFile.getUrl().startsWith("jar://")) return null
|
if (!inJarFile.url.startsWith("jar://")) return null
|
||||||
|
|
||||||
var jarFile = inJarFile
|
var jarFile = inJarFile
|
||||||
while (jarFile.getParent() != null) jarFile = jarFile.getParent()
|
while (jarFile.parent != null) jarFile = jarFile.parent
|
||||||
|
|
||||||
return jarFile
|
return jarFile
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun findLocalJarFile(inJarFile: VirtualFile): VirtualFile? {
|
fun findLocalJarFile(inJarFile: VirtualFile): VirtualFile? {
|
||||||
if (!inJarFile.getUrl().startsWith("jar://")) return null
|
if (!inJarFile.url.startsWith("jar://")) return null
|
||||||
|
|
||||||
val path = inJarFile.getPath()
|
val path = inJarFile.path
|
||||||
|
|
||||||
val jarSeparatorIndex = path.indexOf(URLUtil.JAR_SEPARATOR)
|
val jarSeparatorIndex = path.indexOf(URLUtil.JAR_SEPARATOR)
|
||||||
assert(jarSeparatorIndex >= 0) { "Path passed to JarFileSystem must have jar separator '!/': $path" }
|
assert(jarSeparatorIndex >= 0) { "Path passed to JarFileSystem must have jar separator '!/': $path" }
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi
|
|||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache() {
|
class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache() {
|
||||||
/**
|
/**
|
||||||
* Return kotlin class names from project sources which should be visible from java.
|
* Return kotlin class names from project sources which should be visible from java.
|
||||||
*/
|
*/
|
||||||
@@ -80,7 +80,7 @@ public class KotlinShortNamesCache(private val project: Project) : PsiShortNames
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getAllClassNames(dest: HashSet<String>) {
|
override fun getAllClassNames(dest: HashSet<String>) {
|
||||||
dest.addAll(getAllClassNames())
|
dest.addAll(allClassNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array<PsiMethod>
|
override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array<PsiMethod>
|
||||||
|
|||||||
+3
-3
@@ -28,12 +28,12 @@ import com.intellij.util.cls.ClsFormatException
|
|||||||
import com.intellij.util.containers.ContainerUtil
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
public class ClsJavaStubByVirtualFileCache {
|
class ClsJavaStubByVirtualFileCache {
|
||||||
private class CachedJavaStub(val modificationStamp: Long, val javaFileStub: PsiJavaFileStubImpl)
|
private class CachedJavaStub(val modificationStamp: Long, val javaFileStub: PsiJavaFileStubImpl)
|
||||||
|
|
||||||
private val cache = ContainerUtil.createConcurrentWeakKeySoftValueMap<VirtualFile, CachedJavaStub>()
|
private val cache = ContainerUtil.createConcurrentWeakKeySoftValueMap<VirtualFile, CachedJavaStub>()
|
||||||
|
|
||||||
public fun get(classFile: VirtualFile): PsiJavaFileStubImpl? {
|
fun get(classFile: VirtualFile): PsiJavaFileStubImpl? {
|
||||||
val cached = cache.get(classFile)
|
val cached = cache.get(classFile)
|
||||||
val fileModificationStamp = classFile.modificationStamp
|
val fileModificationStamp = classFile.modificationStamp
|
||||||
if (cached != null && cached.modificationStamp == fileModificationStamp) {
|
if (cached != null && cached.modificationStamp == fileModificationStamp) {
|
||||||
@@ -64,7 +64,7 @@ public class ClsJavaStubByVirtualFileCache {
|
|||||||
companion object {
|
companion object {
|
||||||
private val LOG = Logger.getInstance(ClsJavaStubByVirtualFileCache::class.java)
|
private val LOG = Logger.getInstance(ClsJavaStubByVirtualFileCache::class.java)
|
||||||
|
|
||||||
public fun getInstance(project: Project): ClsJavaStubByVirtualFileCache {
|
fun getInstance(project: Project): ClsJavaStubByVirtualFileCache {
|
||||||
return ServiceManager.getService(project, ClsJavaStubByVirtualFileCache::class.java)
|
return ServiceManager.getService(project, ClsJavaStubByVirtualFileCache::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -35,7 +35,7 @@ import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor
|
|||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
public class CodeFragmentAnalyzer(
|
class CodeFragmentAnalyzer(
|
||||||
private val resolveSession: ResolveSession,
|
private val resolveSession: ResolveSession,
|
||||||
private val qualifierResolver: QualifiedExpressionResolver,
|
private val qualifierResolver: QualifiedExpressionResolver,
|
||||||
private val expressionTypingServices: ExpressionTypingServices,
|
private val expressionTypingServices: ExpressionTypingServices,
|
||||||
@@ -43,10 +43,10 @@ public class CodeFragmentAnalyzer(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
// component dependency cycle
|
// component dependency cycle
|
||||||
public var resolveElementCache: ResolveElementCache? = null
|
var resolveElementCache: ResolveElementCache? = null
|
||||||
@Inject set
|
@Inject set
|
||||||
|
|
||||||
public fun analyzeCodeFragment(codeFragment: KtCodeFragment, trace: BindingTrace, bodyResolveMode: BodyResolveMode) {
|
fun analyzeCodeFragment(codeFragment: KtCodeFragment, trace: BindingTrace, bodyResolveMode: BodyResolveMode) {
|
||||||
val codeFragmentElement = codeFragment.getContentElement()
|
val codeFragmentElement = codeFragment.getContentElement()
|
||||||
|
|
||||||
val (scopeForContextElement, dataFlowInfo) = getScopeAndDataFlowForAnalyzeFragment(codeFragment) {
|
val (scopeForContextElement, dataFlowInfo) = getScopeAndDataFlowForAnalyzeFragment(codeFragment) {
|
||||||
@@ -76,10 +76,10 @@ public class CodeFragmentAnalyzer(
|
|||||||
//TODO: this code should be moved into debugger which should set correct context for its code fragment
|
//TODO: this code should be moved into debugger which should set correct context for its code fragment
|
||||||
private fun KtExpression.correctContextForExpression(): KtExpression {
|
private fun KtExpression.correctContextForExpression(): KtExpression {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is KtProperty -> this.getDelegateExpressionOrInitializer()
|
is KtProperty -> this.delegateExpressionOrInitializer
|
||||||
is KtFunctionLiteral -> this.getBodyExpression()?.getStatements()?.lastOrNull()
|
is KtFunctionLiteral -> this.bodyExpression?.statements?.lastOrNull()
|
||||||
is KtDeclarationWithBody -> this.getBodyExpression()
|
is KtDeclarationWithBody -> this.bodyExpression
|
||||||
is KtBlockExpression -> this.getStatements().lastOrNull()
|
is KtBlockExpression -> this.statements.lastOrNull()
|
||||||
else -> {
|
else -> {
|
||||||
val previousSibling = this.siblings(forward = false, withItself = false).firstIsInstanceOrNull<KtExpression>()
|
val previousSibling = this.siblings(forward = false, withItself = false).firstIsInstanceOrNull<KtExpression>()
|
||||||
if (previousSibling != null) return previousSibling
|
if (previousSibling != null) return previousSibling
|
||||||
@@ -96,7 +96,7 @@ public class CodeFragmentAnalyzer(
|
|||||||
codeFragment: KtCodeFragment,
|
codeFragment: KtCodeFragment,
|
||||||
resolveToElement: (KtElement) -> BindingContext
|
resolveToElement: (KtElement) -> BindingContext
|
||||||
): Pair<LexicalScope, DataFlowInfo>? {
|
): Pair<LexicalScope, DataFlowInfo>? {
|
||||||
val context = codeFragment.getContext()
|
val context = codeFragment.context
|
||||||
if (context !is KtExpression) return null
|
if (context !is KtExpression) return null
|
||||||
|
|
||||||
val scopeForContextElement: LexicalScope?
|
val scopeForContextElement: LexicalScope?
|
||||||
@@ -106,7 +106,7 @@ public class CodeFragmentAnalyzer(
|
|||||||
is KtPrimaryConstructor -> {
|
is KtPrimaryConstructor -> {
|
||||||
val descriptor = resolveSession.getClassDescriptor(context.getContainingClassOrObject(), NoLookupLocation.FROM_IDE) as ClassDescriptorWithResolutionScopes
|
val descriptor = resolveSession.getClassDescriptor(context.getContainingClassOrObject(), NoLookupLocation.FROM_IDE) as ClassDescriptorWithResolutionScopes
|
||||||
|
|
||||||
scopeForContextElement = descriptor.getScopeForInitializerResolution()
|
scopeForContextElement = descriptor.scopeForInitializerResolution
|
||||||
dataFlowInfo = DataFlowInfo.EMPTY
|
dataFlowInfo = DataFlowInfo.EMPTY
|
||||||
}
|
}
|
||||||
is KtSecondaryConstructor -> {
|
is KtSecondaryConstructor -> {
|
||||||
@@ -120,7 +120,7 @@ public class CodeFragmentAnalyzer(
|
|||||||
is KtClassOrObject -> {
|
is KtClassOrObject -> {
|
||||||
val descriptor = resolveSession.getClassDescriptor(context, NoLookupLocation.FROM_IDE) as ClassDescriptorWithResolutionScopes
|
val descriptor = resolveSession.getClassDescriptor(context, NoLookupLocation.FROM_IDE) as ClassDescriptorWithResolutionScopes
|
||||||
|
|
||||||
scopeForContextElement = descriptor.getScopeForMemberDeclarationResolution()
|
scopeForContextElement = descriptor.scopeForMemberDeclarationResolution
|
||||||
dataFlowInfo = DataFlowInfo.EMPTY
|
dataFlowInfo = DataFlowInfo.EMPTY
|
||||||
}
|
}
|
||||||
is KtExpression -> {
|
is KtExpression -> {
|
||||||
@@ -132,7 +132,7 @@ public class CodeFragmentAnalyzer(
|
|||||||
dataFlowInfo = contextForElement.getDataFlowInfo(correctedContext)
|
dataFlowInfo = contextForElement.getDataFlowInfo(correctedContext)
|
||||||
}
|
}
|
||||||
is KtFile -> {
|
is KtFile -> {
|
||||||
scopeForContextElement = resolveSession.getFileScopeProvider().getFileResolutionScope(context)
|
scopeForContextElement = resolveSession.fileScopeProvider.getFileResolutionScope(context)
|
||||||
dataFlowInfo = DataFlowInfo.EMPTY
|
dataFlowInfo = DataFlowInfo.EMPTY
|
||||||
}
|
}
|
||||||
else -> return null
|
else -> return null
|
||||||
|
|||||||
+2
-2
@@ -49,7 +49,7 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
|||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public class IDELightClassGenerationSupport(private val project: Project) : LightClassGenerationSupport() {
|
class IDELightClassGenerationSupport(private val project: Project) : LightClassGenerationSupport() {
|
||||||
private val scopeFileComparator = JavaElementFinder.byClasspathComparator(GlobalSearchScope.allScope(project))
|
private val scopeFileComparator = JavaElementFinder.byClasspathComparator(GlobalSearchScope.allScope(project))
|
||||||
private val psiManager: PsiManager = PsiManager.getInstance(project)
|
private val psiManager: PsiManager = PsiManager.getInstance(project)
|
||||||
|
|
||||||
@@ -182,7 +182,7 @@ public class IDELightClassGenerationSupport(private val project: Project) : Ligh
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun createLightClassForFileFacade(
|
fun createLightClassForFileFacade(
|
||||||
facadeFqName: FqName,
|
facadeFqName: FqName,
|
||||||
facadeFiles: List<KtFile>,
|
facadeFiles: List<KtFile>,
|
||||||
moduleInfo: IdeaModuleInfo
|
moduleInfo: IdeaModuleInfo
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.idea.vfilefinder.KotlinModuleMappingIndex
|
|||||||
import org.jetbrains.kotlin.descriptors.PackagePartProvider
|
import org.jetbrains.kotlin.descriptors.PackagePartProvider
|
||||||
import org.jetbrains.kotlin.load.kotlin.PackageParts
|
import org.jetbrains.kotlin.load.kotlin.PackageParts
|
||||||
|
|
||||||
public class IDEPackagePartProvider(val scope: GlobalSearchScope) : PackagePartProvider {
|
class IDEPackagePartProvider(val scope: GlobalSearchScope) : PackagePartProvider {
|
||||||
|
|
||||||
override fun findPackageParts(packageFqName: String): List<String> {
|
override fun findPackageParts(packageFqName: String): List<String> {
|
||||||
val values: MutableList<PackageParts> = FileBasedIndex.getInstance().getValues(KotlinModuleMappingIndex.KEY, packageFqName, scope)
|
val values: MutableList<PackageParts> = FileBasedIndex.getInstance().getValues(KotlinModuleMappingIndex.KEY, packageFqName, scope)
|
||||||
|
|||||||
+27
-27
@@ -32,9 +32,9 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.utils.emptyOrSingletonList
|
import org.jetbrains.kotlin.utils.emptyOrSingletonList
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public val LIBRARY_NAME_PREFIX: String = "library "
|
val LIBRARY_NAME_PREFIX: String = "library "
|
||||||
|
|
||||||
public interface IdeaModuleInfo : ModuleInfo {
|
interface IdeaModuleInfo : ModuleInfo {
|
||||||
fun contentScope(): GlobalSearchScope
|
fun contentScope(): GlobalSearchScope
|
||||||
|
|
||||||
val moduleOrigin: ModuleOrigin
|
val moduleOrigin: ModuleOrigin
|
||||||
@@ -51,14 +51,14 @@ private fun orderEntryToModuleInfo(project: Project, orderEntry: OrderEntry, pro
|
|||||||
orderEntry.getOwnerModule().toInfos()
|
orderEntry.getOwnerModule().toInfos()
|
||||||
}
|
}
|
||||||
is ModuleOrderEntry -> {
|
is ModuleOrderEntry -> {
|
||||||
orderEntry.getModule()?.toInfos().orEmpty()
|
orderEntry.module?.toInfos().orEmpty()
|
||||||
}
|
}
|
||||||
is LibraryOrderEntry -> {
|
is LibraryOrderEntry -> {
|
||||||
val library = orderEntry.getLibrary() ?: return listOf()
|
val library = orderEntry.library ?: return listOf()
|
||||||
emptyOrSingletonList(LibraryInfo(project, library))
|
emptyOrSingletonList(LibraryInfo(project, library))
|
||||||
}
|
}
|
||||||
is JdkOrderEntry -> {
|
is JdkOrderEntry -> {
|
||||||
val sdk = orderEntry.getJdk() ?: return listOf()
|
val sdk = orderEntry.jdk ?: return listOf()
|
||||||
emptyOrSingletonList(SdkInfo(project, sdk))
|
emptyOrSingletonList(SdkInfo(project, sdk))
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@@ -68,7 +68,7 @@ private fun orderEntryToModuleInfo(project: Project, orderEntry: OrderEntry, pro
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> Module.cached(provider: CachedValueProvider<T>): T {
|
private fun <T> Module.cached(provider: CachedValueProvider<T>): T {
|
||||||
return CachedValuesManager.getManager(getProject()).getCachedValue(this, provider)
|
return CachedValuesManager.getManager(project).getCachedValue(this, provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ideaModelDependencies(module: Module, productionOnly: Boolean): List<IdeaModuleInfo> {
|
fun ideaModelDependencies(module: Module, productionOnly: Boolean): List<IdeaModuleInfo> {
|
||||||
@@ -80,58 +80,58 @@ fun ideaModelDependencies(module: Module, productionOnly: Boolean): List<IdeaMod
|
|||||||
}
|
}
|
||||||
dependencyEnumerator.forEach {
|
dependencyEnumerator.forEach {
|
||||||
orderEntry ->
|
orderEntry ->
|
||||||
result.addAll(orderEntryToModuleInfo(module.getProject(), orderEntry!!, productionOnly))
|
result.addAll(orderEntryToModuleInfo(module.project, orderEntry!!, productionOnly))
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
return result.toList()
|
return result.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ModuleSourceInfo : IdeaModuleInfo {
|
interface ModuleSourceInfo : IdeaModuleInfo {
|
||||||
val module: Module
|
val module: Module
|
||||||
override val moduleOrigin: ModuleOrigin
|
override val moduleOrigin: ModuleOrigin
|
||||||
get() = ModuleOrigin.MODULE
|
get() = ModuleOrigin.MODULE
|
||||||
}
|
}
|
||||||
|
|
||||||
public data class ModuleProductionSourceInfo(override val module: Module) : ModuleSourceInfo {
|
data class ModuleProductionSourceInfo(override val module: Module) : ModuleSourceInfo {
|
||||||
override val name = Name.special("<production sources for module ${module.getName()}>")
|
override val name = Name.special("<production sources for module ${module.name}>")
|
||||||
|
|
||||||
override fun contentScope(): GlobalSearchScope = ModuleProductionSourceScope(module)
|
override fun contentScope(): GlobalSearchScope = ModuleProductionSourceScope(module)
|
||||||
|
|
||||||
override fun dependencies() = module.cached(CachedValueProvider {
|
override fun dependencies() = module.cached(CachedValueProvider {
|
||||||
CachedValueProvider.Result(
|
CachedValueProvider.Result(
|
||||||
ideaModelDependencies(module, productionOnly = true),
|
ideaModelDependencies(module, productionOnly = true),
|
||||||
ProjectRootModificationTracker.getInstance(module.getProject()))
|
ProjectRootModificationTracker.getInstance(module.project))
|
||||||
})
|
})
|
||||||
|
|
||||||
override fun friends() = listOf(module.testSourceInfo())
|
override fun friends() = listOf(module.testSourceInfo())
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: (module refactoring) do not create ModuleTestSourceInfo when there are no test roots for module
|
//TODO: (module refactoring) do not create ModuleTestSourceInfo when there are no test roots for module
|
||||||
public data class ModuleTestSourceInfo(override val module: Module) : ModuleSourceInfo {
|
data class ModuleTestSourceInfo(override val module: Module) : ModuleSourceInfo {
|
||||||
override val name = Name.special("<test sources for module ${module.getName()}>")
|
override val name = Name.special("<test sources for module ${module.name}>")
|
||||||
|
|
||||||
override fun contentScope(): GlobalSearchScope = ModuleTestSourceScope(module)
|
override fun contentScope(): GlobalSearchScope = ModuleTestSourceScope(module)
|
||||||
|
|
||||||
override fun dependencies() = module.cached(CachedValueProvider {
|
override fun dependencies() = module.cached(CachedValueProvider {
|
||||||
CachedValueProvider.Result(
|
CachedValueProvider.Result(
|
||||||
ideaModelDependencies(module, productionOnly = false),
|
ideaModelDependencies(module, productionOnly = false),
|
||||||
ProjectRootModificationTracker.getInstance(module.getProject()))
|
ProjectRootModificationTracker.getInstance(module.project))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun ModuleSourceInfo.isTests() = this is ModuleTestSourceInfo
|
internal fun ModuleSourceInfo.isTests() = this is ModuleTestSourceInfo
|
||||||
|
|
||||||
public fun Module.productionSourceInfo(): ModuleProductionSourceInfo = ModuleProductionSourceInfo(this)
|
fun Module.productionSourceInfo(): ModuleProductionSourceInfo = ModuleProductionSourceInfo(this)
|
||||||
public fun Module.testSourceInfo(): ModuleTestSourceInfo = ModuleTestSourceInfo(this)
|
fun Module.testSourceInfo(): ModuleTestSourceInfo = ModuleTestSourceInfo(this)
|
||||||
|
|
||||||
private abstract class ModuleSourceScope(val module: Module) : GlobalSearchScope(module.getProject()) {
|
private abstract class ModuleSourceScope(val module: Module) : GlobalSearchScope(module.project) {
|
||||||
override fun compare(file1: VirtualFile, file2: VirtualFile) = 0
|
override fun compare(file1: VirtualFile, file2: VirtualFile) = 0
|
||||||
override fun isSearchInModuleContent(aModule: Module) = aModule == module
|
override fun isSearchInModuleContent(aModule: Module) = aModule == module
|
||||||
override fun isSearchInLibraries() = false
|
override fun isSearchInLibraries() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ModuleProductionSourceScope(module: Module) : ModuleSourceScope(module) {
|
private class ModuleProductionSourceScope(module: Module) : ModuleSourceScope(module) {
|
||||||
val moduleFileIndex = ModuleRootManager.getInstance(module).getFileIndex()
|
val moduleFileIndex = ModuleRootManager.getInstance(module).fileIndex
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
@@ -144,7 +144,7 @@ private class ModuleProductionSourceScope(module: Module) : ModuleSourceScope(mo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ModuleTestSourceScope(module: Module) : ModuleSourceScope(module) {
|
private class ModuleTestSourceScope(module: Module) : ModuleSourceScope(module) {
|
||||||
val moduleFileIndex = ModuleRootManager.getInstance(module).getFileIndex()
|
val moduleFileIndex = ModuleRootManager.getInstance(module).fileIndex
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
@@ -156,11 +156,11 @@ private class ModuleTestSourceScope(module: Module) : ModuleSourceScope(module)
|
|||||||
override fun contains(file: VirtualFile) = moduleFileIndex.isInTestSourceContent(file)
|
override fun contains(file: VirtualFile) = moduleFileIndex.isInTestSourceContent(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
public data class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo {
|
data class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo {
|
||||||
override val moduleOrigin: ModuleOrigin
|
override val moduleOrigin: ModuleOrigin
|
||||||
get() = ModuleOrigin.LIBRARY
|
get() = ModuleOrigin.LIBRARY
|
||||||
|
|
||||||
override val name: Name = Name.special("<$LIBRARY_NAME_PREFIX${library.getName()}>")
|
override val name: Name = Name.special("<$LIBRARY_NAME_PREFIX${library.name}>")
|
||||||
|
|
||||||
override fun contentScope(): GlobalSearchScope = LibraryWithoutSourceScope(project, library)
|
override fun contentScope(): GlobalSearchScope = LibraryWithoutSourceScope(project, library)
|
||||||
|
|
||||||
@@ -179,14 +179,14 @@ public data class LibraryInfo(val project: Project, val library: Library) : Idea
|
|||||||
return result.toList()
|
return result.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString() = "LibraryInfo(libraryName=${library.getName()})"
|
override fun toString() = "LibraryInfo(libraryName=${library.name})"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal data class LibrarySourceInfo(val project: Project, val library: Library) : IdeaModuleInfo {
|
internal data class LibrarySourceInfo(val project: Project, val library: Library) : IdeaModuleInfo {
|
||||||
override val moduleOrigin: ModuleOrigin
|
override val moduleOrigin: ModuleOrigin
|
||||||
get() = ModuleOrigin.OTHER
|
get() = ModuleOrigin.OTHER
|
||||||
|
|
||||||
override val name: Name = Name.special("<sources for library ${library.getName()}>")
|
override val name: Name = Name.special("<sources for library ${library.name}>")
|
||||||
|
|
||||||
override fun contentScope() = GlobalSearchScope.EMPTY_SCOPE
|
override fun contentScope() = GlobalSearchScope.EMPTY_SCOPE
|
||||||
|
|
||||||
@@ -197,15 +197,15 @@ internal data class LibrarySourceInfo(val project: Project, val library: Library
|
|||||||
return listOf(this) + LibraryInfo(project, library).dependencies()
|
return listOf(this) + LibraryInfo(project, library).dependencies()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString() = "LibrarySourceInfo(libraryName=${library.getName()})"
|
override fun toString() = "LibrarySourceInfo(libraryName=${library.name})"
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: (module refactoring) there should be separate SdkSourceInfo but there are no kotlin source in existing sdks for now :)
|
//TODO: (module refactoring) there should be separate SdkSourceInfo but there are no kotlin source in existing sdks for now :)
|
||||||
public data class SdkInfo(val project: Project, val sdk: Sdk) : IdeaModuleInfo {
|
data class SdkInfo(val project: Project, val sdk: Sdk) : IdeaModuleInfo {
|
||||||
override val moduleOrigin: ModuleOrigin
|
override val moduleOrigin: ModuleOrigin
|
||||||
get() = ModuleOrigin.LIBRARY
|
get() = ModuleOrigin.LIBRARY
|
||||||
|
|
||||||
override val name: Name = Name.special("<$LIBRARY_NAME_PREFIX${sdk.getName()}>")
|
override val name: Name = Name.special("<$LIBRARY_NAME_PREFIX${sdk.name}>")
|
||||||
|
|
||||||
override fun contentScope(): GlobalSearchScope = SdkScope(project, sdk)
|
override fun contentScope(): GlobalSearchScope = SdkScope(project, sdk)
|
||||||
|
|
||||||
@@ -234,7 +234,7 @@ private class LibraryWithoutSourceScope(project: Project, private val library: L
|
|||||||
|
|
||||||
//TODO: (module refactoring) android sdk has modified scope
|
//TODO: (module refactoring) android sdk has modified scope
|
||||||
private class SdkScope(project: Project, private val sdk: Sdk) :
|
private class SdkScope(project: Project, private val sdk: Sdk) :
|
||||||
LibraryScopeBase(project, sdk.getRootProvider().getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
|
LibraryScopeBase(project, sdk.rootProvider.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
|
||||||
|
|
||||||
override fun equals(other: Any?) = other is SdkScope && sdk == other.sdk
|
override fun equals(other: Any?) = other is SdkScope && sdk == other.sdk
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -97,7 +97,7 @@ private fun JavaDescriptorResolver.resolveMethod(method: JavaMethod): FunctionDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun JavaDescriptorResolver.resolveConstructor(constructor: JavaConstructor): ConstructorDescriptor? {
|
private fun JavaDescriptorResolver.resolveConstructor(constructor: JavaConstructor): ConstructorDescriptor? {
|
||||||
return resolveClass(constructor.getContainingClass())?.getConstructors()?.findByJavaElement(constructor)
|
return resolveClass(constructor.containingClass)?.constructors?.findByJavaElement(constructor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JavaDescriptorResolver.resolveField(field: JavaField): PropertyDescriptor? {
|
private fun JavaDescriptorResolver.resolveField(field: JavaField): PropertyDescriptor? {
|
||||||
@@ -105,21 +105,21 @@ private fun JavaDescriptorResolver.resolveField(field: JavaField): PropertyDescr
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun JavaDescriptorResolver.getContainingScope(member: JavaMember): MemberScope? {
|
private fun JavaDescriptorResolver.getContainingScope(member: JavaMember): MemberScope? {
|
||||||
val containingClass = resolveClass(member.getContainingClass())
|
val containingClass = resolveClass(member.containingClass)
|
||||||
return if (member.isStatic())
|
return if (member.isStatic)
|
||||||
containingClass?.getStaticScope()
|
containingClass?.staticScope
|
||||||
else
|
else
|
||||||
containingClass?.getDefaultType()?.getMemberScope()
|
containingClass?.defaultType?.memberScope
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : DeclarationDescriptorWithSource> Collection<T>.findByJavaElement(javaElement: JavaElement): T? {
|
private fun <T : DeclarationDescriptorWithSource> Collection<T>.findByJavaElement(javaElement: JavaElement): T? {
|
||||||
return firstOrNull { member ->
|
return firstOrNull { member ->
|
||||||
val memberJavaElement = (member.getOriginal().getSource() as? JavaSourceElement)?.javaElement
|
val memberJavaElement = (member.original.source as? JavaSourceElement)?.javaElement
|
||||||
when {
|
when {
|
||||||
memberJavaElement == javaElement ->
|
memberJavaElement == javaElement ->
|
||||||
true
|
true
|
||||||
memberJavaElement is JavaElementImpl<*> && javaElement is JavaElementImpl<*> ->
|
memberJavaElement is JavaElementImpl<*> && javaElement is JavaElementImpl<*> ->
|
||||||
memberJavaElement.getPsi().isEquivalentTo(javaElement.getPsi())
|
memberJavaElement.psi.isEquivalentTo(javaElement.psi)
|
||||||
else ->
|
else ->
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
|||||||
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
|
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
|
||||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
||||||
|
|
||||||
public object JsAnalyzerFacade : AnalyzerFacade<PlatformAnalysisParameters>() {
|
object JsAnalyzerFacade : AnalyzerFacade<PlatformAnalysisParameters>() {
|
||||||
|
|
||||||
override fun <M : ModuleInfo> createResolverForModule(
|
override fun <M : ModuleInfo> createResolverForModule(
|
||||||
moduleInfo: M,
|
moduleInfo: M,
|
||||||
@@ -55,7 +55,7 @@ public object JsAnalyzerFacade : AnalyzerFacade<PlatformAnalysisParameters>() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val container = createContainerForLazyResolve(moduleContext, declarationProviderFactory, BindingTraceContext(), JsPlatform, targetEnvironment)
|
val container = createContainerForLazyResolve(moduleContext, declarationProviderFactory, BindingTraceContext(), JsPlatform, targetEnvironment)
|
||||||
var packageFragmentProvider = container.get<ResolveSession>().getPackageFragmentProvider()
|
var packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider
|
||||||
|
|
||||||
if (moduleInfo is LibraryInfo && KotlinJavaScriptLibraryDetectionUtil.isKotlinJavaScriptLibrary(moduleInfo.library)) {
|
if (moduleInfo is LibraryInfo && KotlinJavaScriptLibraryDetectionUtil.isKotlinJavaScriptLibrary(moduleInfo.library)) {
|
||||||
val providers = moduleInfo.library.getFiles(OrderRootType.CLASSES)
|
val providers = moduleInfo.library.getFiles(OrderRootType.CLASSES)
|
||||||
|
|||||||
+3
-4
@@ -24,11 +24,10 @@ import com.intellij.psi.util.CachedValueProvider
|
|||||||
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
||||||
|
|
||||||
//TODO: this should go away to support cross-platform projects
|
//TODO: this should go away to support cross-platform projects
|
||||||
public object JsProjectDetector {
|
object JsProjectDetector {
|
||||||
@JvmStatic
|
@JvmStatic fun isJsProject(project: Project): Boolean {
|
||||||
public fun isJsProject(project: Project): Boolean {
|
|
||||||
return CachedValuesManager.getManager(project).getCachedValue(project) {
|
return CachedValuesManager.getManager(project).getCachedValue(project) {
|
||||||
val result = ModuleManager.getInstance(project).getModules().any { ProjectStructureUtil.isJsKotlinModule(it) }
|
val result = ModuleManager.getInstance(project).modules.any { ProjectStructureUtil.isJsKotlinModule(it) }
|
||||||
CachedValueProvider.Result(result, ProjectRootModificationTracker.getInstance(project))
|
CachedValueProvider.Result(result, ProjectRootModificationTracker.getInstance(project))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-8
@@ -44,17 +44,16 @@ import org.jetbrains.kotlin.utils.keysToMap
|
|||||||
|
|
||||||
internal val LOG = Logger.getInstance(KotlinCacheService::class.java)
|
internal val LOG = Logger.getInstance(KotlinCacheService::class.java)
|
||||||
|
|
||||||
public class KotlinCacheService(val project: Project) {
|
class KotlinCacheService(val project: Project) {
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic fun getInstance(project: Project): KotlinCacheService = ServiceManager.getService(project, KotlinCacheService::class.java)!!
|
||||||
public fun getInstance(project: Project): KotlinCacheService = ServiceManager.getService(project, KotlinCacheService::class.java)!!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getResolutionFacade(elements: List<KtElement>): ResolutionFacade {
|
fun getResolutionFacade(elements: List<KtElement>): ResolutionFacade {
|
||||||
return getFacadeToAnalyzeFiles(elements.map { it.getContainingKtFile() })
|
return getFacadeToAnalyzeFiles(elements.map { it.getContainingKtFile() })
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getSuppressionCache(): KotlinSuppressCache = kotlinSuppressCache.value
|
fun getSuppressionCache(): KotlinSuppressCache = kotlinSuppressCache.value
|
||||||
|
|
||||||
private val globalFacadesPerPlatform = listOf(JvmPlatform, JsPlatform).keysToMap { platform -> GlobalFacade(platform) }
|
private val globalFacadesPerPlatform = listOf(JvmPlatform, JsPlatform).keysToMap { platform -> GlobalFacade(platform) }
|
||||||
|
|
||||||
@@ -84,8 +83,7 @@ public class KotlinCacheService(val project: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Use JetElement.getResolutionFacade(), please avoid introducing new usages")
|
@Deprecated("Use JetElement.getResolutionFacade(), please avoid introducing new usages") fun <T : Any> getProjectService(platform: TargetPlatform, ideaModuleInfo: IdeaModuleInfo, serviceClass: Class<T>): T {
|
||||||
public fun <T : Any> getProjectService(platform: TargetPlatform, ideaModuleInfo: IdeaModuleInfo, serviceClass: Class<T>): T {
|
|
||||||
return globalFacade(platform).resolverForModuleInfo(ideaModuleInfo).componentProvider.getService(serviceClass)
|
return globalFacade(platform).resolverForModuleInfo(ideaModuleInfo).componentProvider.getService(serviceClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +217,7 @@ public class KotlinCacheService(val project: Project) {
|
|||||||
}.toSet()
|
}.toSet()
|
||||||
|
|
||||||
private fun KtCodeFragment.getContextFile(): KtFile? {
|
private fun KtCodeFragment.getContextFile(): KtFile? {
|
||||||
val contextElement = getContext() ?: return null
|
val contextElement = context ?: return null
|
||||||
val contextFile = (contextElement as? KtElement)?.getContainingKtFile()
|
val contextFile = (contextElement as? KtElement)?.getContainingKtFile()
|
||||||
?: throw AssertionError("Analyzing kotlin code fragment of type $javaClass with java context of type ${contextElement.javaClass}")
|
?: throw AssertionError("Analyzing kotlin code fragment of type $javaClass with java context of type ${contextElement.javaClass}")
|
||||||
return if (contextFile is KtCodeFragment) contextFile.getContextFile() else contextFile
|
return if (contextFile is KtCodeFragment) contextFile.getContextFile() else contextFile
|
||||||
|
|||||||
+4
-4
@@ -26,15 +26,15 @@ import org.jetbrains.kotlin.asJava.KotlinCodeBlockModificationListener
|
|||||||
// Synthetic file for completion can be modified without sending tree changed events and sequence of completions can lead to inconsistent
|
// Synthetic file for completion can be modified without sending tree changed events and sequence of completions can lead to inconsistent
|
||||||
// resolve session being cached for such a file otherwise.
|
// resolve session being cached for such a file otherwise.
|
||||||
// This code is not tested. See KT-6216 for an example.
|
// This code is not tested. See KT-6216 for an example.
|
||||||
public class KotlinOutOfBlockCompletionModificationTracker() : SimpleModificationTracker() {
|
class KotlinOutOfBlockCompletionModificationTracker() : SimpleModificationTracker() {
|
||||||
companion object {
|
companion object {
|
||||||
public fun getInstance(project: Project): KotlinOutOfBlockCompletionModificationTracker
|
fun getInstance(project: Project): KotlinOutOfBlockCompletionModificationTracker
|
||||||
= ServiceManager.getService(project, KotlinOutOfBlockCompletionModificationTracker::class.java)!!
|
= ServiceManager.getService(project, KotlinOutOfBlockCompletionModificationTracker::class.java)!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun performCompletionWithOutOfBlockTracking(completionPosition: PsiElement, body: () -> Unit) {
|
fun performCompletionWithOutOfBlockTracking(completionPosition: PsiElement, body: () -> Unit) {
|
||||||
if (KotlinCodeBlockModificationListener.isInsideCodeBlock(completionPosition)) {
|
if (KotlinCodeBlockModificationListener.isInsideCodeBlock(completionPosition)) {
|
||||||
body()
|
body()
|
||||||
return
|
return
|
||||||
@@ -43,6 +43,6 @@ public fun performCompletionWithOutOfBlockTracking(completionPosition: PsiElemen
|
|||||||
body()
|
body()
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
KotlinOutOfBlockCompletionModificationTracker.getInstance(completionPosition.getProject()).incModificationCount()
|
KotlinOutOfBlockCompletionModificationTracker.getInstance(completionPosition.project).incModificationCount()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -84,7 +84,7 @@ internal class PerFileAnalysisCache(val file: KtFile, val componentProvider: Com
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun analyze(analyzableElement: KtElement): AnalysisResult {
|
private fun analyze(analyzableElement: KtElement): AnalysisResult {
|
||||||
val project = analyzableElement.getProject()
|
val project = analyzableElement.project
|
||||||
if (DumbService.isDumb(project)) {
|
if (DumbService.isDumb(project)) {
|
||||||
return AnalysisResult.EMPTY
|
return AnalysisResult.EMPTY
|
||||||
}
|
}
|
||||||
@@ -158,7 +158,7 @@ private object KotlinResolveDataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val resolveSession = componentProvider.get<ResolveSession>()
|
val resolveSession = componentProvider.get<ResolveSession>()
|
||||||
val trace = DelegatingBindingTrace(resolveSession.getBindingContext(), "Trace for resolution of " + analyzableElement)
|
val trace = DelegatingBindingTrace(resolveSession.bindingContext, "Trace for resolution of " + analyzableElement)
|
||||||
|
|
||||||
val targetPlatform = TargetPlatformDetector.getPlatform(analyzableElement.getContainingKtFile())
|
val targetPlatform = TargetPlatformDetector.getPlatform(analyzableElement.getContainingKtFile())
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ private object KotlinResolveDataProvider {
|
|||||||
listOf(analyzableElement)
|
listOf(analyzableElement)
|
||||||
)
|
)
|
||||||
return AnalysisResult.success(
|
return AnalysisResult.success(
|
||||||
trace.getBindingContext(),
|
trace.bindingContext,
|
||||||
module
|
module
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -25,20 +25,20 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
|
|||||||
class KtLightClassForDecompiledDeclaration(
|
class KtLightClassForDecompiledDeclaration(
|
||||||
private val clsClass: ClsClassImpl,
|
private val clsClass: ClsClassImpl,
|
||||||
private val origin: KtClassOrObject?
|
private val origin: KtClassOrObject?
|
||||||
) : KtWrappingLightClass(clsClass.getManager()) {
|
) : KtWrappingLightClass(clsClass.manager) {
|
||||||
private val fqName = origin?.getFqName() ?: FqName(clsClass.getQualifiedName())
|
private val fqName = origin?.fqName ?: FqName(clsClass.qualifiedName)
|
||||||
|
|
||||||
override fun copy() = this
|
override fun copy() = this
|
||||||
|
|
||||||
override fun getOwnInnerClasses(): List<PsiClass> {
|
override fun getOwnInnerClasses(): List<PsiClass> {
|
||||||
val nestedClasses = origin?.getDeclarations()?.filterIsInstance<KtClassOrObject>() ?: emptyList()
|
val nestedClasses = origin?.declarations?.filterIsInstance<KtClassOrObject>() ?: emptyList()
|
||||||
return clsClass.getOwnInnerClasses().map { innerClsClass ->
|
return clsClass.ownInnerClasses.map { innerClsClass ->
|
||||||
KtLightClassForDecompiledDeclaration(innerClsClass as ClsClassImpl,
|
KtLightClassForDecompiledDeclaration(innerClsClass as ClsClassImpl,
|
||||||
nestedClasses.firstOrNull { innerClsClass.getName() == it.getName() })
|
nestedClasses.firstOrNull { innerClsClass.name == it.name })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNavigationElement() = origin?.getNavigationElement() ?: super.getNavigationElement()
|
override fun getNavigationElement() = origin?.navigationElement ?: super.getNavigationElement()
|
||||||
|
|
||||||
override fun getDelegate() = clsClass
|
override fun getDelegate() = clsClass
|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -36,14 +36,14 @@ import com.intellij.openapi.projectRoots.Sdk
|
|||||||
import com.intellij.openapi.roots.JdkOrderEntry
|
import com.intellij.openapi.roots.JdkOrderEntry
|
||||||
import com.intellij.openapi.roots.ModuleSourceOrderEntry
|
import com.intellij.openapi.roots.ModuleSourceOrderEntry
|
||||||
|
|
||||||
public class LibraryDependenciesCache(private val project: Project) {
|
class LibraryDependenciesCache(private val project: Project) {
|
||||||
|
|
||||||
//NOTE: used LibraryRuntimeClasspathScope as reference
|
//NOTE: used LibraryRuntimeClasspathScope as reference
|
||||||
public fun getLibrariesAndSdksUsedWith(library: Library): Pair<List<Library>, List<Sdk>> {
|
fun getLibrariesAndSdksUsedWith(library: Library): Pair<List<Library>, List<Sdk>> {
|
||||||
val processedModules = LinkedHashSet<Module>()
|
val processedModules = LinkedHashSet<Module>()
|
||||||
val condition = Condition<OrderEntry>() { orderEntry ->
|
val condition = Condition<OrderEntry>() { orderEntry ->
|
||||||
if (orderEntry is ModuleOrderEntry) {
|
if (orderEntry is ModuleOrderEntry) {
|
||||||
val module = orderEntry.getModule()
|
val module = orderEntry.module
|
||||||
module != null && module !in processedModules
|
module != null && module !in processedModules
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -59,17 +59,17 @@ public class LibraryDependenciesCache(private val project: Project) {
|
|||||||
|
|
||||||
ModuleRootManager.getInstance(module).orderEntries().recursively().satisfying(condition).process(object : RootPolicy<Unit>() {
|
ModuleRootManager.getInstance(module).orderEntries().recursively().satisfying(condition).process(object : RootPolicy<Unit>() {
|
||||||
override fun visitModuleSourceOrderEntry(moduleSourceOrderEntry: ModuleSourceOrderEntry?, value: Unit?): Unit? {
|
override fun visitModuleSourceOrderEntry(moduleSourceOrderEntry: ModuleSourceOrderEntry?, value: Unit?): Unit? {
|
||||||
processedModules.addIfNotNull(moduleSourceOrderEntry?.getOwnerModule())
|
processedModules.addIfNotNull(moduleSourceOrderEntry?.ownerModule)
|
||||||
return Unit
|
return Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun visitLibraryOrderEntry(libraryOrderEntry: LibraryOrderEntry?, value: Unit?): Unit? {
|
override fun visitLibraryOrderEntry(libraryOrderEntry: LibraryOrderEntry?, value: Unit?): Unit? {
|
||||||
libraries.addIfNotNull(libraryOrderEntry?.getLibrary())
|
libraries.addIfNotNull(libraryOrderEntry?.library)
|
||||||
return Unit
|
return Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitJdkOrderEntry(jdkOrderEntry: JdkOrderEntry?, value: Unit?): Unit? {
|
override fun visitJdkOrderEntry(jdkOrderEntry: JdkOrderEntry?, value: Unit?): Unit? {
|
||||||
sdks.addIfNotNull(jdkOrderEntry?.getJdk())
|
sdks.addIfNotNull(jdkOrderEntry?.jdk)
|
||||||
return Unit
|
return Unit
|
||||||
}
|
}
|
||||||
}, Unit)
|
}, Unit)
|
||||||
@@ -90,12 +90,12 @@ public class LibraryDependenciesCache(private val project: Project) {
|
|||||||
val modulesLibraryIsUsedIn: MultiMap<Library, Module> = MultiMap.createSet()
|
val modulesLibraryIsUsedIn: MultiMap<Library, Module> = MultiMap.createSet()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
ModuleManager.getInstance(project).getModules().forEach {
|
ModuleManager.getInstance(project).modules.forEach {
|
||||||
module ->
|
module ->
|
||||||
ModuleRootManager.getInstance(module).getOrderEntries().forEach {
|
ModuleRootManager.getInstance(module).orderEntries.forEach {
|
||||||
entry ->
|
entry ->
|
||||||
if (entry is LibraryOrderEntry) {
|
if (entry is LibraryOrderEntry) {
|
||||||
val library = entry.getLibrary()
|
val library = entry.library
|
||||||
if (library != null) {
|
if (library != null) {
|
||||||
modulesLibraryIsUsedIn.putValue(library, module)
|
modulesLibraryIsUsedIn.putValue(library, module)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -58,7 +58,7 @@ fun createModuleResolverProvider(
|
|||||||
|
|
||||||
val jvmPlatformParameters = JvmPlatformParameters {
|
val jvmPlatformParameters = JvmPlatformParameters {
|
||||||
javaClass: JavaClass ->
|
javaClass: JavaClass ->
|
||||||
val psiClass = (javaClass as JavaClassImpl).getPsi()
|
val psiClass = (javaClass as JavaClassImpl).psi
|
||||||
psiClass.getNullableModuleInfo()
|
psiClass.getNullableModuleInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,21 +79,21 @@ fun createModuleResolverProvider(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun collectAllModuleInfosFromIdeaModel(project: Project): List<IdeaModuleInfo> {
|
private fun collectAllModuleInfosFromIdeaModel(project: Project): List<IdeaModuleInfo> {
|
||||||
val ideaModules = ModuleManager.getInstance(project).getModules().toList()
|
val ideaModules = ModuleManager.getInstance(project).modules.toList()
|
||||||
val modulesSourcesInfos = ideaModules.flatMap { listOf(it.productionSourceInfo(), it.testSourceInfo()) }
|
val modulesSourcesInfos = ideaModules.flatMap { listOf(it.productionSourceInfo(), it.testSourceInfo()) }
|
||||||
|
|
||||||
//TODO: (module refactoring) include libraries that are not among dependencies of any module
|
//TODO: (module refactoring) include libraries that are not among dependencies of any module
|
||||||
val ideaLibraries = ideaModules.flatMap {
|
val ideaLibraries = ideaModules.flatMap {
|
||||||
ModuleRootManager.getInstance(it).getOrderEntries().filterIsInstance<LibraryOrderEntry>().map {
|
ModuleRootManager.getInstance(it).orderEntries.filterIsInstance<LibraryOrderEntry>().map {
|
||||||
it.getLibrary()
|
it.library
|
||||||
}
|
}
|
||||||
}.filterNotNull().toSet()
|
}.filterNotNull().toSet()
|
||||||
|
|
||||||
val librariesInfos = ideaLibraries.map { LibraryInfo(project, it) }
|
val librariesInfos = ideaLibraries.map { LibraryInfo(project, it) }
|
||||||
|
|
||||||
val ideaSdks = ideaModules.flatMap {
|
val ideaSdks = ideaModules.flatMap {
|
||||||
ModuleRootManager.getInstance(it).getOrderEntries().filterIsInstance<JdkOrderEntry>().map {
|
ModuleRootManager.getInstance(it).orderEntries.filterIsInstance<JdkOrderEntry>().map {
|
||||||
it.getJdk()
|
it.jdk
|
||||||
}
|
}
|
||||||
}.filterNotNull().toSet()
|
}.filterNotNull().toSet()
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ internal class ProjectResolutionFacade(
|
|||||||
fun getAnalysisResultsForElements(elements: Collection<KtElement>): AnalysisResult {
|
fun getAnalysisResultsForElements(elements: Collection<KtElement>): AnalysisResult {
|
||||||
assert(elements.isNotEmpty()) { "elements collection should not be empty" }
|
assert(elements.isNotEmpty()) { "elements collection should not be empty" }
|
||||||
val slruCache = synchronized(analysisResults) {
|
val slruCache = synchronized(analysisResults) {
|
||||||
analysisResults.getValue()!!
|
analysisResults.value!!
|
||||||
}
|
}
|
||||||
val results = elements.map {
|
val results = elements.map {
|
||||||
val perFileCache = synchronized(slruCache) {
|
val perFileCache = synchronized(slruCache) {
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ class SynchronizedCachedValue<V>(project: Project, provider: () -> CachedValuePr
|
|||||||
trackValue
|
trackValue
|
||||||
)
|
)
|
||||||
|
|
||||||
public fun getValue(): V {
|
fun getValue(): V {
|
||||||
return synchronized(cachedValue) {
|
return synchronized(cachedValue) {
|
||||||
cachedValue.getValue()
|
cachedValue.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,14 +44,14 @@ fun PsiElement.getNullableModuleInfo(): IdeaModuleInfo? = this.getModuleInfo { r
|
|||||||
private fun PsiElement.getModuleInfo(onFailure: (String) -> IdeaModuleInfo?): IdeaModuleInfo? {
|
private fun PsiElement.getModuleInfo(onFailure: (String) -> IdeaModuleInfo?): IdeaModuleInfo? {
|
||||||
if (this is KtLightElement<*, *>) return this.getModuleInfoForLightElement()
|
if (this is KtLightElement<*, *>) return this.getModuleInfoForLightElement()
|
||||||
|
|
||||||
val containingJetFile = (this as? KtElement)?.getContainingFile() as? KtFile
|
val containingJetFile = (this as? KtElement)?.containingFile as? KtFile
|
||||||
val context = containingJetFile?.analysisContext
|
val context = containingJetFile?.analysisContext
|
||||||
if (context != null) return context.getModuleInfo()
|
if (context != null) return context.getModuleInfo()
|
||||||
|
|
||||||
val doNotAnalyze = containingJetFile?.doNotAnalyze
|
val doNotAnalyze = containingJetFile?.doNotAnalyze
|
||||||
if (doNotAnalyze != null) {
|
if (doNotAnalyze != null) {
|
||||||
return onFailure(
|
return onFailure(
|
||||||
"Should not analyze element: ${getText()} in file ${containingJetFile?.getName() ?: " <no file>"}\n$doNotAnalyze"
|
"Should not analyze element: ${text} in file ${containingJetFile?.name ?: " <no file>"}\n$doNotAnalyze"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ private fun PsiElement.getModuleInfo(onFailure: (String) -> IdeaModuleInfo?): Id
|
|||||||
return getModuleInfoByVirtualFile(
|
return getModuleInfoByVirtualFile(
|
||||||
project,
|
project,
|
||||||
virtualFile,
|
virtualFile,
|
||||||
isDecompiledFile = (containingFile as? KtFile)?.isCompiled() ?: false
|
isDecompiledFile = (containingFile as? KtFile)?.isCompiled ?: false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,11 +82,11 @@ private fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFil
|
|||||||
if (module != null) {
|
if (module != null) {
|
||||||
fun warnIfDecompiled() {
|
fun warnIfDecompiled() {
|
||||||
if (isDecompiledFile) {
|
if (isDecompiledFile) {
|
||||||
LOG.warn("Decompiled file for ${virtualFile.getCanonicalPath()} is in content of $module")
|
LOG.warn("Decompiled file for ${virtualFile.canonicalPath} is in content of $module")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val moduleFileIndex = ModuleRootManager.getInstance(module).getFileIndex()
|
val moduleFileIndex = ModuleRootManager.getInstance(module).fileIndex
|
||||||
if (moduleFileIndex.isInTestSourceContent(virtualFile)) {
|
if (moduleFileIndex.isInTestSourceContent(virtualFile)) {
|
||||||
warnIfDecompiled()
|
warnIfDecompiled()
|
||||||
return module.testSourceInfo()
|
return module.testSourceInfo()
|
||||||
@@ -102,7 +102,7 @@ private fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFil
|
|||||||
entries@ for (orderEntry in orderEntries) {
|
entries@ for (orderEntry in orderEntries) {
|
||||||
when (orderEntry) {
|
when (orderEntry) {
|
||||||
is LibraryOrderEntry -> {
|
is LibraryOrderEntry -> {
|
||||||
val library = orderEntry.getLibrary() ?: continue@entries
|
val library = orderEntry.library ?: continue@entries
|
||||||
if (ProjectRootsUtil.isLibraryClassFile(project, virtualFile) && !isDecompiledFile) {
|
if (ProjectRootsUtil.isLibraryClassFile(project, virtualFile) && !isDecompiledFile) {
|
||||||
return LibraryInfo(project, library)
|
return LibraryInfo(project, library)
|
||||||
}
|
}
|
||||||
@@ -111,7 +111,7 @@ private fun getModuleInfoByVirtualFile(project: Project, virtualFile: VirtualFil
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is JdkOrderEntry -> {
|
is JdkOrderEntry -> {
|
||||||
val sdk = orderEntry.getJdk() ?: continue@entries
|
val sdk = orderEntry.jdk ?: continue@entries
|
||||||
return SdkInfo(project, sdk)
|
return SdkInfo(project, sdk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -30,7 +30,7 @@ fun GlobalContextImpl.withCompositeExceptionTrackerUnderSameLock(): GlobalContex
|
|||||||
|
|
||||||
private class CompositeExceptionTracker(val delegate: ExceptionTracker) : ExceptionTracker() {
|
private class CompositeExceptionTracker(val delegate: ExceptionTracker) : ExceptionTracker() {
|
||||||
override fun getModificationCount(): Long {
|
override fun getModificationCount(): Long {
|
||||||
return super.getModificationCount() + delegate.getModificationCount()
|
return super.getModificationCount() + delegate.modificationCount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ private class ExceptionTrackerWithProcessCanceledReport() : ExceptionTracker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun GlobalContext(logProcessCanceled: Boolean): GlobalContextImpl {
|
fun GlobalContext(logProcessCanceled: Boolean): GlobalContextImpl {
|
||||||
val tracker = if (logProcessCanceled) ExceptionTrackerWithProcessCanceledReport() else ExceptionTracker()
|
val tracker = if (logProcessCanceled) ExceptionTrackerWithProcessCanceledReport() else ExceptionTracker()
|
||||||
return GlobalContextImpl(LockBasedStorageManager.createWithExceptionHandling(tracker), tracker)
|
return GlobalContextImpl(LockBasedStorageManager.createWithExceptionHandling(tracker), tracker)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import com.intellij.openapi.roots.ProjectRootModificationTracker
|
|||||||
import java.util.HashSet
|
import java.util.HashSet
|
||||||
|
|
||||||
//NOTE: this is an approximation that may contain more module infos then the exact solution
|
//NOTE: this is an approximation that may contain more module infos then the exact solution
|
||||||
public fun ModuleSourceInfo.getDependentModules(): Set<ModuleSourceInfo> {
|
fun ModuleSourceInfo.getDependentModules(): Set<ModuleSourceInfo> {
|
||||||
val dependents = getDependents(module)
|
val dependents = getDependents(module)
|
||||||
if (isTests()) {
|
if (isTests()) {
|
||||||
return dependents.mapTo(HashSet<ModuleSourceInfo>()) { it.testSourceInfo() }
|
return dependents.mapTo(HashSet<ModuleSourceInfo>()) { it.testSourceInfo() }
|
||||||
@@ -47,12 +47,12 @@ private fun getDependents(module: Module): Set<Module> {
|
|||||||
|
|
||||||
val processedExporting = THashSet<Module>()
|
val processedExporting = THashSet<Module>()
|
||||||
|
|
||||||
val index = getModuleIndex(module.getProject())
|
val index = getModuleIndex(module.project)
|
||||||
|
|
||||||
val walkingQueue = Queue<Module>(10)
|
val walkingQueue = Queue<Module>(10)
|
||||||
walkingQueue.addLast(module)
|
walkingQueue.addLast(module)
|
||||||
|
|
||||||
while (!walkingQueue.isEmpty()) {
|
while (!walkingQueue.isEmpty) {
|
||||||
val current = walkingQueue.pullFirst()
|
val current = walkingQueue.pullFirst()
|
||||||
processedExporting.add(current!!)
|
processedExporting.add(current!!)
|
||||||
result.addAll(index.plainUsages[current])
|
result.addAll(index.plainUsages[current])
|
||||||
@@ -74,12 +74,12 @@ private class ModuleIndex {
|
|||||||
private fun getModuleIndex(project: Project): ModuleIndex {
|
private fun getModuleIndex(project: Project): ModuleIndex {
|
||||||
return CachedValuesManager.getManager(project).getCachedValue(project) {
|
return CachedValuesManager.getManager(project).getCachedValue(project) {
|
||||||
val index = ModuleIndex()
|
val index = ModuleIndex()
|
||||||
for (module in ModuleManager.getInstance(project).getModules()) {
|
for (module in ModuleManager.getInstance(project).modules) {
|
||||||
for (orderEntry in ModuleRootManager.getInstance(module).getOrderEntries()) {
|
for (orderEntry in ModuleRootManager.getInstance(module).orderEntries) {
|
||||||
if (orderEntry is ModuleOrderEntry) {
|
if (orderEntry is ModuleOrderEntry) {
|
||||||
val referenced = orderEntry.getModule()
|
val referenced = orderEntry.module
|
||||||
if (referenced != null) {
|
if (referenced != null) {
|
||||||
val map = if (orderEntry.isExported()) index.exportingUsages else index.plainUsages
|
val map = if (orderEntry.isExported) index.exportingUsages else index.plainUsages
|
||||||
map.putValue(referenced, module)
|
map.putValue(referenced, module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,19 +32,19 @@ import org.jetbrains.kotlin.resolve.ImportPath
|
|||||||
import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver
|
import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
|
||||||
public fun KtElement.getResolutionFacade(): ResolutionFacade {
|
fun KtElement.getResolutionFacade(): ResolutionFacade {
|
||||||
return KotlinCacheService.getInstance(getProject()).getResolutionFacade(listOf(this))
|
return KotlinCacheService.getInstance(project).getResolutionFacade(listOf(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KtDeclaration.resolveToDescriptor(): DeclarationDescriptor {
|
fun KtDeclaration.resolveToDescriptor(): DeclarationDescriptor {
|
||||||
return getResolutionFacade().resolveToDescriptor(this)
|
return getResolutionFacade().resolveToDescriptor(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KtDeclaration.resolveToDescriptorIfAny(): DeclarationDescriptor? {
|
fun KtDeclaration.resolveToDescriptorIfAny(): DeclarationDescriptor? {
|
||||||
return analyze(BodyResolveMode.PARTIAL).get(BindingContext.DECLARATION_TO_DESCRIPTOR, this)
|
return analyze(BodyResolveMode.PARTIAL).get(BindingContext.DECLARATION_TO_DESCRIPTOR, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KtFile.resolveImportReference(fqName: FqName): Collection<DeclarationDescriptor> {
|
fun KtFile.resolveImportReference(fqName: FqName): Collection<DeclarationDescriptor> {
|
||||||
val facade = getResolutionFacade()
|
val facade = getResolutionFacade()
|
||||||
return facade.resolveImportReference(facade.moduleDescriptor, fqName)
|
return facade.resolveImportReference(facade.moduleDescriptor, fqName)
|
||||||
}
|
}
|
||||||
@@ -54,30 +54,29 @@ public fun KtFile.resolveImportReference(fqName: FqName): Collection<Declaration
|
|||||||
// analyze - see ResolveSessionForBodies, ResolveElementCache
|
// analyze - see ResolveSessionForBodies, ResolveElementCache
|
||||||
// analyzeFully - see KotlinResolveCache, KotlinResolveDataProvider
|
// analyzeFully - see KotlinResolveCache, KotlinResolveDataProvider
|
||||||
// In the future these two approaches should be unified
|
// In the future these two approaches should be unified
|
||||||
@JvmOverloads
|
@JvmOverloads fun KtElement.analyze(bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext {
|
||||||
public fun KtElement.analyze(bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext {
|
|
||||||
return getResolutionFacade().analyze(this, bodyResolveMode)
|
return getResolutionFacade().analyze(this, bodyResolveMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KtElement.analyzeAndGetResult(): AnalysisResult {
|
fun KtElement.analyzeAndGetResult(): AnalysisResult {
|
||||||
val resolutionFacade = getResolutionFacade()
|
val resolutionFacade = getResolutionFacade()
|
||||||
return AnalysisResult.success(resolutionFacade.analyze(this), resolutionFacade.moduleDescriptor)
|
return AnalysisResult.success(resolutionFacade.analyze(this), resolutionFacade.moduleDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KtElement.findModuleDescriptor(): ModuleDescriptor {
|
fun KtElement.findModuleDescriptor(): ModuleDescriptor {
|
||||||
return getResolutionFacade().moduleDescriptor
|
return getResolutionFacade().moduleDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KtElement.analyzeFully(): BindingContext {
|
fun KtElement.analyzeFully(): BindingContext {
|
||||||
return analyzeFullyAndGetResult().bindingContext
|
return analyzeFullyAndGetResult().bindingContext
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KtElement.analyzeFullyAndGetResult(vararg extraFiles: KtFile): AnalysisResult {
|
fun KtElement.analyzeFullyAndGetResult(vararg extraFiles: KtFile): AnalysisResult {
|
||||||
return KotlinCacheService.getInstance(getProject()).getResolutionFacade(listOf(this) + extraFiles.toList()).analyzeFullyAndGetResult(listOf(this))
|
return KotlinCacheService.getInstance(project).getResolutionFacade(listOf(this) + extraFiles.toList()).analyzeFullyAndGetResult(listOf(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
public fun ResolutionFacade.resolveImportReference(
|
fun ResolutionFacade.resolveImportReference(
|
||||||
moduleDescriptor: ModuleDescriptor,
|
moduleDescriptor: ModuleDescriptor,
|
||||||
fqName: FqName
|
fqName: FqName
|
||||||
): Collection<DeclarationDescriptor> {
|
): Collection<DeclarationDescriptor> {
|
||||||
@@ -90,7 +89,7 @@ public fun ResolutionFacade.resolveImportReference(
|
|||||||
//NOTE: idea default API returns module search scope for file under module but not in source or production source (for example, test data )
|
//NOTE: idea default API returns module search scope for file under module but not in source or production source (for example, test data )
|
||||||
// this scope can't be used to search for kotlin declarations in index in order to resolve in that case
|
// this scope can't be used to search for kotlin declarations in index in order to resolve in that case
|
||||||
// see com.intellij.psi.impl.file.impl.ResolveScopeManagerImpl.getInherentResolveScope
|
// see com.intellij.psi.impl.file.impl.ResolveScopeManagerImpl.getInherentResolveScope
|
||||||
public fun getResolveScope(file: KtFile): GlobalSearchScope {
|
fun getResolveScope(file: KtFile): GlobalSearchScope {
|
||||||
if (file is KtCodeFragment) {
|
if (file is KtCodeFragment) {
|
||||||
file.forcedResolveScope?.let { return KotlinSourceFilterScope.sourceAndClassFiles(it, file.project) }
|
file.forcedResolveScope?.let { return KotlinSourceFilterScope.sourceAndClassFiles(it, file.project) }
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -23,19 +23,19 @@ import org.jetbrains.kotlin.idea.decompiler.navigation.findDecompiledDeclaration
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.sequenceOfLazyValues
|
import org.jetbrains.kotlin.utils.addToStdlib.sequenceOfLazyValues
|
||||||
|
|
||||||
public object DescriptorToSourceUtilsIde {
|
object DescriptorToSourceUtilsIde {
|
||||||
// Returns PSI element for descriptor. If there are many relevant elements (e.g. it is fake override
|
// Returns PSI element for descriptor. If there are many relevant elements (e.g. it is fake override
|
||||||
// with multiple declarations), finds any of them. It can find declarations in builtins or decompiled code.
|
// with multiple declarations), finds any of them. It can find declarations in builtins or decompiled code.
|
||||||
public fun getAnyDeclaration(project: Project, descriptor: DeclarationDescriptor): PsiElement? {
|
fun getAnyDeclaration(project: Project, descriptor: DeclarationDescriptor): PsiElement? {
|
||||||
return getDeclarationsStream(project, descriptor).firstOrNull()
|
return getDeclarationsStream(project, descriptor).firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
public fun getAllDeclarations(project: Project, targetDescriptor: DeclarationDescriptor): Collection<PsiElement> {
|
fun getAllDeclarations(project: Project, targetDescriptor: DeclarationDescriptor): Collection<PsiElement> {
|
||||||
val result = getDeclarationsStream(project, targetDescriptor).toHashSet()
|
val result = getDeclarationsStream(project, targetDescriptor).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
|
||||||
// this is needed to avoid duplicated results for references to declaration in same library source file
|
// this is needed to avoid duplicated results for references to declaration in same library source file
|
||||||
return result.filter { element -> result.none { element != it && it.getNavigationElement() == element } }
|
return result.filter { element -> result.none { element != it && it.navigationElement == element } }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDeclarationsStream(project: Project, targetDescriptor: DeclarationDescriptor): Sequence<PsiElement> {
|
private fun getDeclarationsStream(project: Project, targetDescriptor: DeclarationDescriptor): Sequence<PsiElement> {
|
||||||
|
|||||||
+8
-8
@@ -27,7 +27,7 @@ object KotlinFileReferencesResolver {
|
|||||||
resolveQualifiers: Boolean = true,
|
resolveQualifiers: Boolean = true,
|
||||||
resolveShortNames: Boolean = true
|
resolveShortNames: Boolean = true
|
||||||
): Map<KtReferenceExpression, BindingContext> {
|
): Map<KtReferenceExpression, BindingContext> {
|
||||||
return (element.getContainingFile() as? KtFile)?.let { file ->
|
return (element.containingFile as? KtFile)?.let { file ->
|
||||||
resolve(file, listOf(element), resolveQualifiers, resolveShortNames)
|
resolve(file, listOf(element), resolveQualifiers, resolveShortNames)
|
||||||
} ?: Collections.emptyMap()
|
} ?: Collections.emptyMap()
|
||||||
}
|
}
|
||||||
@@ -52,15 +52,15 @@ object KotlinFileReferencesResolver {
|
|||||||
private val resolutionFacade = file.getResolutionFacade()
|
private val resolutionFacade = file.getResolutionFacade()
|
||||||
private val resolveMap = LinkedHashMap<KtReferenceExpression, BindingContext>()
|
private val resolveMap = LinkedHashMap<KtReferenceExpression, BindingContext>()
|
||||||
|
|
||||||
public val result: Map<KtReferenceExpression, BindingContext> = resolveMap
|
val result: Map<KtReferenceExpression, BindingContext> = resolveMap
|
||||||
|
|
||||||
override fun visitUserType(userType: KtUserType) {
|
override fun visitUserType(userType: KtUserType) {
|
||||||
if (resolveQualifiers) {
|
if (resolveQualifiers) {
|
||||||
userType.acceptChildren(this)
|
userType.acceptChildren(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resolveShortNames || userType.getQualifier() != null) {
|
if (resolveShortNames || userType.qualifier != null) {
|
||||||
val referenceExpression = userType.getReferenceExpression()
|
val referenceExpression = userType.referenceExpression
|
||||||
if (referenceExpression != null) {
|
if (referenceExpression != null) {
|
||||||
resolveMap[referenceExpression] = resolutionFacade.analyze(referenceExpression)
|
resolveMap[referenceExpression] = resolutionFacade.analyze(referenceExpression)
|
||||||
}
|
}
|
||||||
@@ -68,16 +68,16 @@ object KotlinFileReferencesResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitQualifiedExpression(expression: KtQualifiedExpression) {
|
override fun visitQualifiedExpression(expression: KtQualifiedExpression) {
|
||||||
val receiverExpression = expression.getReceiverExpression()
|
val receiverExpression = expression.receiverExpression
|
||||||
if (resolveQualifiers || resolutionFacade.analyze(expression)[BindingContext.QUALIFIER, receiverExpression] == null) {
|
if (resolveQualifiers || resolutionFacade.analyze(expression)[BindingContext.QUALIFIER, receiverExpression] == null) {
|
||||||
receiverExpression.accept(this)
|
receiverExpression.accept(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
val referenceExpression = expression.getSelectorExpression()?.referenceExpression()
|
val referenceExpression = expression.selectorExpression?.referenceExpression()
|
||||||
if (referenceExpression != null) {
|
if (referenceExpression != null) {
|
||||||
resolveMap[referenceExpression] = resolutionFacade.analyze(referenceExpression)
|
resolveMap[referenceExpression] = resolutionFacade.analyze(referenceExpression)
|
||||||
}
|
}
|
||||||
expression.getSelectorExpression()?.accept(this)
|
expression.selectorExpression?.accept(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
||||||
@@ -89,4 +89,4 @@ object KotlinFileReferencesResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun KtExpression.referenceExpression(): KtReferenceExpression? =
|
fun KtExpression.referenceExpression(): KtReferenceExpression? =
|
||||||
(if (this is KtCallExpression) getCalleeExpression() else this) as? KtReferenceExpression
|
(if (this is KtCallExpression) calleeExpression else this) as? KtReferenceExpression
|
||||||
|
|||||||
+8
-8
@@ -38,10 +38,10 @@ private var Project.elementsToShorten: MutableSet<ShorteningRequest>?
|
|||||||
* When one refactoring invokes another this value must be set to false so that shortening wait-set is not cleared
|
* When one refactoring invokes another this value must be set to false so that shortening wait-set is not cleared
|
||||||
* and previously collected references are processed correctly. Afterwards it must be reset to original value
|
* and previously collected references are processed correctly. Afterwards it must be reset to original value
|
||||||
*/
|
*/
|
||||||
public var Project.ensureElementsToShortenIsEmptyBeforeRefactoring: Boolean
|
var Project.ensureElementsToShortenIsEmptyBeforeRefactoring: Boolean
|
||||||
by NotNullableUserDataProperty(Key.create("ENSURE_ELEMENTS_TO_SHORTEN_IS_EMPTY"), true)
|
by NotNullableUserDataProperty(Key.create("ENSURE_ELEMENTS_TO_SHORTEN_IS_EMPTY"), true)
|
||||||
|
|
||||||
public fun Project.runWithElementsToShortenIsEmptyIgnored(action: () -> Unit) {
|
fun Project.runWithElementsToShortenIsEmptyIgnored(action: () -> Unit) {
|
||||||
val ensureElementsToShortenIsEmpty = ensureElementsToShortenIsEmptyBeforeRefactoring
|
val ensureElementsToShortenIsEmpty = ensureElementsToShortenIsEmptyBeforeRefactoring
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -62,14 +62,14 @@ private fun Project.getOrCreateElementsToShorten(): MutableSet<ShorteningRequest
|
|||||||
return elements
|
return elements
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun KtElement.addToShorteningWaitSet(options: Options = Options.DEFAULT) {
|
fun KtElement.addToShorteningWaitSet(options: Options = Options.DEFAULT) {
|
||||||
assert(ApplicationManager.getApplication()!!.isWriteAccessAllowed()) { "Write access needed" }
|
assert(ApplicationManager.getApplication()!!.isWriteAccessAllowed) { "Write access needed" }
|
||||||
val project = getProject()
|
val project = project
|
||||||
val elementPointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(this)
|
val elementPointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(this)
|
||||||
project.getOrCreateElementsToShorten().add(ShorteningRequest(elementPointer, options))
|
project.getOrCreateElementsToShorten().add(ShorteningRequest(elementPointer, options))
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun performDelayedShortening(project: Project) {
|
fun performDelayedShortening(project: Project) {
|
||||||
project.elementsToShorten?.let { requests ->
|
project.elementsToShorten?.let { requests ->
|
||||||
project.elementsToShorten = null
|
project.elementsToShorten = null
|
||||||
val elementToOptions = requests.mapNotNull { req -> req.pointer.element?.let { it to req.options } }.toMap()
|
val elementToOptions = requests.mapNotNull { req -> req.pointer.element?.let { it to req.options } }.toMap()
|
||||||
@@ -79,9 +79,9 @@ public fun performDelayedShortening(project: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val LOG = Logger.getInstance(Project::class.java.getCanonicalName())
|
private val LOG = Logger.getInstance(Project::class.java.canonicalName)
|
||||||
|
|
||||||
public fun prepareElementsToShorten(project: Project) {
|
fun prepareElementsToShorten(project: Project) {
|
||||||
val elementsToShorten = project.elementsToShorten
|
val elementsToShorten = project.elementsToShorten
|
||||||
if (project.ensureElementsToShortenIsEmptyBeforeRefactoring && elementsToShorten != null && !elementsToShorten.isEmpty()) {
|
if (project.ensureElementsToShortenIsEmptyBeforeRefactoring && elementsToShorten != null && !elementsToShorten.isEmpty()) {
|
||||||
LOG.warn("Waiting set for reference shortening is not empty")
|
LOG.warn("Waiting set for reference shortening is not empty")
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class ModuleTypeCacheManager private constructor(project: Project) {
|
|||||||
|
|
||||||
private class VfsModificationTracker(project: Project): SimpleModificationTracker() {
|
private class VfsModificationTracker(project: Project): SimpleModificationTracker() {
|
||||||
init {
|
init {
|
||||||
val connection = project.getMessageBus().connect();
|
val connection = project.messageBus.connect();
|
||||||
connection.subscribe(VirtualFileManager.VFS_CHANGES, BulkVirtualFileListenerAdapter(
|
connection.subscribe(VirtualFileManager.VFS_CHANGES, BulkVirtualFileListenerAdapter(
|
||||||
object : VirtualFileAdapter() {
|
object : VirtualFileAdapter() {
|
||||||
override fun propertyChanged(event: VirtualFilePropertyEvent) {
|
override fun propertyChanged(event: VirtualFilePropertyEvent) {
|
||||||
@@ -95,11 +95,11 @@ private fun computeType(module: Module) =
|
|||||||
private val DEFAULT_SCRIPT_NAME = "build.gradle"
|
private val DEFAULT_SCRIPT_NAME = "build.gradle"
|
||||||
|
|
||||||
private fun isGradleModule(module: Module): Boolean {
|
private fun isGradleModule(module: Module): Boolean {
|
||||||
val moduleFile = module.getModuleFile()
|
val moduleFile = module.moduleFile
|
||||||
if (moduleFile == null){
|
if (moduleFile == null){
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val buildFile = moduleFile.getParent()?.findChild(DEFAULT_SCRIPT_NAME)
|
val buildFile = moduleFile.parent?.findChild(DEFAULT_SCRIPT_NAME)
|
||||||
return buildFile != null && buildFile.exists()
|
return buildFile != null && buildFile.exists()
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -35,8 +35,8 @@ class KotlinDecompiledFileViewProvider(
|
|||||||
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.getProject(), file, KotlinFileType.INSTANCE)
|
val psiFile = createFile(manager.project, file, KotlinFileType.INSTANCE)
|
||||||
val text = psiFile?.getText() ?: ""
|
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 {
|
||||||
@@ -53,7 +53,7 @@ class KotlinDecompiledFileViewProvider(
|
|||||||
return factory(this)
|
return factory(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createCopy(copy: VirtualFile) = KotlinDecompiledFileViewProvider(getManager(), copy, false, factory)
|
override fun createCopy(copy: VirtualFile) = KotlinDecompiledFileViewProvider(manager, copy, false, factory)
|
||||||
|
|
||||||
override fun getContents() = content.get()
|
override fun getContents() = content.get()
|
||||||
}
|
}
|
||||||
@@ -46,17 +46,17 @@ open class KtDecompiledFile(
|
|||||||
buildDecompiledText(provider.virtualFile)
|
buildDecompiledText(provider.virtualFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getDeclarationForDescriptor(descriptor: DeclarationDescriptor): KtDeclaration? {
|
fun getDeclarationForDescriptor(descriptor: DeclarationDescriptor): KtDeclaration? {
|
||||||
val original = descriptor.getOriginal()
|
val original = descriptor.original
|
||||||
|
|
||||||
if (original is ValueParameterDescriptor) {
|
if (original is ValueParameterDescriptor) {
|
||||||
val callable = original.getContainingDeclaration()
|
val callable = original.containingDeclaration
|
||||||
val callableDeclaration = getDeclarationForDescriptor(callable) as? KtCallableDeclaration ?: return null
|
val callableDeclaration = getDeclarationForDescriptor(callable) as? KtCallableDeclaration ?: return null
|
||||||
return callableDeclaration.getValueParameters()[original.index]
|
return callableDeclaration.valueParameters[original.index]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (original is ConstructorDescriptor && original.isPrimary()) {
|
if (original is ConstructorDescriptor && original.isPrimary) {
|
||||||
val classOrObject = getDeclarationForDescriptor(original.getContainingDeclaration()) as? KtClassOrObject
|
val classOrObject = getDeclarationForDescriptor(original.containingDeclaration) as? KtClassOrObject
|
||||||
return classOrObject?.getPrimaryConstructor() ?: classOrObject
|
return classOrObject?.getPrimaryConstructor() ?: classOrObject
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ open class KtDecompiledFile(
|
|||||||
|
|
||||||
private fun DeclarationDescriptor.findElementForDescriptor(): KtDeclaration? {
|
private fun DeclarationDescriptor.findElementForDescriptor(): KtDeclaration? {
|
||||||
return decompiledText.get().renderedDescriptorsToRange[descriptorToKey(this)]?.let { range ->
|
return decompiledText.get().renderedDescriptorsToRange[descriptorToKey(this)]?.let { range ->
|
||||||
PsiTreeUtil.findElementOfClassAtRange(this@KtDecompiledFile, range.getStartOffset(), range.getEndOffset(), KtDeclaration::class.java)
|
PsiTreeUtil.findElementOfClassAtRange(this@KtDecompiledFile, range.startOffset, range.endOffset, KtDeclaration::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -65,7 +65,7 @@ class KotlinBuiltInDecompiler : ClassFileDecompilers.Full() {
|
|||||||
|
|
||||||
private val decompilerRendererForBuiltIns = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() }
|
private val decompilerRendererForBuiltIns = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() }
|
||||||
|
|
||||||
public fun buildDecompiledTextForBuiltIns(
|
fun buildDecompiledTextForBuiltIns(
|
||||||
builtInFile: VirtualFile
|
builtInFile: VirtualFile
|
||||||
): DecompiledText {
|
): DecompiledText {
|
||||||
val directory = builtInFile.parent!!
|
val directory = builtInFile.parent!!
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.*
|
import org.jetbrains.kotlin.serialization.deserialization.*
|
||||||
|
|
||||||
public class KotlinBuiltInDeserializerForDecompiler(
|
class KotlinBuiltInDeserializerForDecompiler(
|
||||||
packageDirectory: VirtualFile,
|
packageDirectory: VirtualFile,
|
||||||
packageFqName: FqName,
|
packageFqName: FqName,
|
||||||
private val nameResolver: NameResolver
|
private val nameResolver: NameResolver
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
|
|||||||
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
|
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
|
|
||||||
public class KotlinBuiltInStubBuilder : ClsStubBuilder() {
|
class KotlinBuiltInStubBuilder : ClsStubBuilder() {
|
||||||
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + 1
|
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + 1
|
||||||
|
|
||||||
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import com.intellij.openapi.vfs.VirtualFile
|
|||||||
import org.jetbrains.kotlin.builtins.BuiltInsSerializedResourcePaths
|
import org.jetbrains.kotlin.builtins.BuiltInsSerializedResourcePaths
|
||||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||||
|
|
||||||
public object KotlinBuiltInClassFileType : FileType {
|
object KotlinBuiltInClassFileType : FileType {
|
||||||
override fun getName() = "kotlin_class"
|
override fun getName() = "kotlin_class"
|
||||||
|
|
||||||
override fun getDescription() = "Kotlin builtin class"
|
override fun getDescription() = "Kotlin builtin class"
|
||||||
@@ -37,7 +37,7 @@ public object KotlinBuiltInClassFileType : FileType {
|
|||||||
override fun getCharset(file: VirtualFile, content: ByteArray) = null
|
override fun getCharset(file: VirtualFile, content: ByteArray) = null
|
||||||
}
|
}
|
||||||
|
|
||||||
public object KotlinBuiltInPackageFileType : FileType {
|
object KotlinBuiltInPackageFileType : FileType {
|
||||||
override fun getName() = "kotlin_package"
|
override fun getName() = "kotlin_package"
|
||||||
|
|
||||||
override fun getDescription() = "Kotlin builtin package"
|
override fun getDescription() = "Kotlin builtin package"
|
||||||
|
|||||||
+7
-7
@@ -29,8 +29,8 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
/**
|
/**
|
||||||
* Checks if this file is a compiled Kotlin class file (not necessarily ABI-compatible with the current plugin)
|
* Checks if this file is a compiled Kotlin class file (not necessarily ABI-compatible with the current plugin)
|
||||||
*/
|
*/
|
||||||
public fun isKotlinJvmCompiledFile(file: VirtualFile): Boolean {
|
fun isKotlinJvmCompiledFile(file: VirtualFile): Boolean {
|
||||||
if (file.getExtension() != JavaClassFileType.INSTANCE!!.getDefaultExtension()) {
|
if (file.extension != JavaClassFileType.INSTANCE!!.defaultExtension) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,10 +45,10 @@ public fun isKotlinJvmCompiledFile(file: VirtualFile): Boolean {
|
|||||||
/**
|
/**
|
||||||
* Checks if this file is a compiled Kotlin class file ABI-compatible with the current plugin
|
* Checks if this file is a compiled Kotlin class file ABI-compatible with the current plugin
|
||||||
*/
|
*/
|
||||||
public fun isKotlinWithCompatibleAbiVersion(file: VirtualFile): Boolean {
|
fun isKotlinWithCompatibleAbiVersion(file: VirtualFile): Boolean {
|
||||||
if (!isKotlinJvmCompiledFile(file)) return false
|
if (!isKotlinJvmCompiledFile(file)) return false
|
||||||
|
|
||||||
val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.getClassHeader()
|
val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.classHeader
|
||||||
return header != null && header.isCompatibleAbiVersion
|
return header != null && header.isCompatibleAbiVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ public fun isKotlinWithCompatibleAbiVersion(file: VirtualFile): Boolean {
|
|||||||
* Checks if this file is a compiled "internal" Kotlin class, i.e. a Kotlin class (not necessarily ABI-compatible with the current plugin)
|
* Checks if this file is a compiled "internal" Kotlin class, i.e. a Kotlin class (not necessarily ABI-compatible with the current plugin)
|
||||||
* which should NOT be decompiled (and, as a result, shown under the library in the Project view, be searchable via Find class, etc.)
|
* which should NOT be decompiled (and, as a result, shown under the library in the Project view, be searchable via Find class, etc.)
|
||||||
*/
|
*/
|
||||||
public fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean {
|
fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean {
|
||||||
if (!isKotlinJvmCompiledFile(file)) {
|
if (!isKotlinJvmCompiledFile(file)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -71,14 +71,14 @@ public fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean {
|
|||||||
header.isLocalClass || header.syntheticClassKind == "PACKAGE_PART"
|
header.isLocalClass || header.syntheticClassKind == "PACKAGE_PART"
|
||||||
}
|
}
|
||||||
|
|
||||||
public object HasCompiledKotlinInJar : JarUserDataManager.JarBooleanPropertyCounter(HasCompiledKotlinInJar::class.simpleName!!) {
|
object HasCompiledKotlinInJar : JarUserDataManager.JarBooleanPropertyCounter(HasCompiledKotlinInJar::class.simpleName!!) {
|
||||||
override fun hasProperty(file: VirtualFile) = isKotlinJvmCompiledFile(file)
|
override fun hasProperty(file: VirtualFile) = isKotlinJvmCompiledFile(file)
|
||||||
|
|
||||||
fun isInNoKotlinJar(file: VirtualFile): Boolean =
|
fun isInNoKotlinJar(file: VirtualFile): Boolean =
|
||||||
JarUserDataManager.hasFileWithProperty(HasCompiledKotlinInJar, file) == false
|
JarUserDataManager.hasFileWithProperty(HasCompiledKotlinInJar, file) == false
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun findMultifileClassParts(file: VirtualFile, multifileClass: KotlinJvmBinaryClass): List<KotlinJvmBinaryClass> {
|
fun findMultifileClassParts(file: VirtualFile, multifileClass: KotlinJvmBinaryClass): List<KotlinJvmBinaryClass> {
|
||||||
val packageFqName = multifileClass.classId.packageFqName
|
val packageFqName = multifileClass.classId.packageFqName
|
||||||
val partsFinder = DirectoryBasedClassFinder(file.parent!!, packageFqName)
|
val partsFinder = DirectoryBasedClassFinder(file.parent!!, packageFqName)
|
||||||
val partNames = multifileClass.classHeader.filePartClassNames ?: return emptyList()
|
val partNames = multifileClass.classHeader.filePartClassNames ?: return emptyList()
|
||||||
|
|||||||
+7
-7
@@ -36,14 +36,14 @@ import org.jetbrains.kotlin.serialization.deserialization.DeserializationCompone
|
|||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
||||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
|
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
|
||||||
|
|
||||||
public fun DeserializerForClassfileDecompiler(classFile: VirtualFile): DeserializerForClassfileDecompiler {
|
fun DeserializerForClassfileDecompiler(classFile: VirtualFile): DeserializerForClassfileDecompiler {
|
||||||
val kotlinClass = KotlinBinaryClassCache.getKotlinBinaryClass(classFile)
|
val kotlinClass = KotlinBinaryClassCache.getKotlinBinaryClass(classFile)
|
||||||
assert(kotlinClass != null) { "Decompiled data factory shouldn't be called on an unsupported file: " + classFile }
|
assert(kotlinClass != null) { "Decompiled data factory shouldn't be called on an unsupported file: " + classFile }
|
||||||
val packageFqName = kotlinClass!!.classId.packageFqName
|
val packageFqName = kotlinClass!!.classId.packageFqName
|
||||||
return DeserializerForClassfileDecompiler(classFile.parent!!, packageFqName)
|
return DeserializerForClassfileDecompiler(classFile.parent!!, packageFqName)
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DeserializerForClassfileDecompiler(
|
class DeserializerForClassfileDecompiler(
|
||||||
packageDirectory: VirtualFile,
|
packageDirectory: VirtualFile,
|
||||||
directoryPackageFqName: FqName
|
directoryPackageFqName: FqName
|
||||||
) : DeserializerForDecompilerBase(packageDirectory, directoryPackageFqName) {
|
) : DeserializerForDecompilerBase(packageDirectory, directoryPackageFqName) {
|
||||||
@@ -74,7 +74,7 @@ public class DeserializerForClassfileDecompiler(
|
|||||||
val annotationData = header?.annotationData
|
val annotationData = header?.annotationData
|
||||||
val strings = header?.strings
|
val strings = header?.strings
|
||||||
if (annotationData == null || strings == null) {
|
if (annotationData == null || strings == null) {
|
||||||
LOG.error("Could not read annotation data for $facadeFqName from ${binaryClassForPackageClass?.getClassId()}")
|
LOG.error("Could not read annotation data for $facadeFqName from ${binaryClassForPackageClass?.classId}")
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings)
|
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings)
|
||||||
@@ -97,10 +97,10 @@ class DirectoryBasedClassFinder(
|
|||||||
override fun findKotlinClass(javaClass: JavaClass) = findKotlinClass(javaClass.classId)
|
override fun findKotlinClass(javaClass: JavaClass) = findKotlinClass(javaClass.classId)
|
||||||
|
|
||||||
override fun findKotlinClass(classId: ClassId): KotlinJvmBinaryClass? {
|
override fun findKotlinClass(classId: ClassId): KotlinJvmBinaryClass? {
|
||||||
if (classId.getPackageFqName() != directoryPackageFqName) {
|
if (classId.packageFqName != directoryPackageFqName) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val targetName = classId.getRelativeClassName().pathSegments().joinToString("$", postfix = ".class")
|
val targetName = classId.relativeClassName.pathSegments().joinToString("$", postfix = ".class")
|
||||||
val virtualFile = packageDirectory.findChild(targetName)
|
val virtualFile = packageDirectory.findChild(targetName)
|
||||||
if (virtualFile != null && isKotlinWithCompatibleAbiVersion(virtualFile)) {
|
if (virtualFile != null && isKotlinWithCompatibleAbiVersion(virtualFile)) {
|
||||||
return KotlinBinaryClassCache.getKotlinBinaryClass(virtualFile)
|
return KotlinBinaryClassCache.getKotlinBinaryClass(virtualFile)
|
||||||
@@ -134,6 +134,6 @@ class DirectoryBasedDataFinder(
|
|||||||
|
|
||||||
private val JavaClass.classId: ClassId
|
private val JavaClass.classId: ClassId
|
||||||
get() {
|
get() {
|
||||||
val outer = getOuterClass()
|
val outer = outerClass
|
||||||
return if (outer == null) ClassId.topLevel(getFqName()!!) else outer.classId.createNestedClassId(getName())
|
return if (outer == null) ClassId.topLevel(fqName!!) else outer.classId.createNestedClassId(name)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -37,7 +37,7 @@ import org.jetbrains.kotlin.types.flexibility
|
|||||||
import org.jetbrains.kotlin.types.isFlexible
|
import org.jetbrains.kotlin.types.isFlexible
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public class KotlinClassFileDecompiler : ClassFileDecompilers.Full() {
|
class KotlinClassFileDecompiler : ClassFileDecompilers.Full() {
|
||||||
private val stubBuilder = KotlinClsStubBuilder()
|
private val stubBuilder = KotlinClsStubBuilder()
|
||||||
|
|
||||||
override fun accepts(file: VirtualFile) = isKotlinJvmCompiledFile(file)
|
override fun accepts(file: VirtualFile) = isKotlinJvmCompiledFile(file)
|
||||||
@@ -68,22 +68,22 @@ private val decompilerRendererForClassFiles = DescriptorRenderer.withOptions {
|
|||||||
private val FILE_ABI_VERSION_MARKER: String = "FILE_ABI"
|
private val FILE_ABI_VERSION_MARKER: String = "FILE_ABI"
|
||||||
private val CURRENT_ABI_VERSION_MARKER: String = "CURRENT_ABI"
|
private val CURRENT_ABI_VERSION_MARKER: String = "CURRENT_ABI"
|
||||||
|
|
||||||
public 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 = "// This class file was compiled with different version of Kotlin compiler and can't be decompiled."
|
||||||
public val INCOMPATIBLE_ABI_VERSION_COMMENT: String =
|
val INCOMPATIBLE_ABI_VERSION_COMMENT: String =
|
||||||
"$INCOMPATIBLE_ABI_VERSION_GENERAL_COMMENT\n" +
|
"$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"
|
||||||
|
|
||||||
public fun buildDecompiledTextForClassFile(
|
fun buildDecompiledTextForClassFile(
|
||||||
classFile: VirtualFile,
|
classFile: VirtualFile,
|
||||||
resolver: ResolverForDecompiler = DeserializerForClassfileDecompiler(classFile)
|
resolver: ResolverForDecompiler = DeserializerForClassfileDecompiler(classFile)
|
||||||
): DecompiledText {
|
): DecompiledText {
|
||||||
val kotlinClass = KotlinBinaryClassCache.getKotlinBinaryClass(classFile)
|
val kotlinClass = KotlinBinaryClassCache.getKotlinBinaryClass(classFile)
|
||||||
assert(kotlinClass != null) { "Decompiled data factory shouldn't be called on an unsupported file: " + classFile }
|
assert(kotlinClass != null) { "Decompiled data factory shouldn't be called on an unsupported file: " + classFile }
|
||||||
val classId = kotlinClass!!.getClassId()
|
val classId = kotlinClass!!.classId
|
||||||
val classHeader = kotlinClass.getClassHeader()
|
val classHeader = kotlinClass.classHeader
|
||||||
val packageFqName = classId.getPackageFqName()
|
val packageFqName = classId.packageFqName
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
!classHeader.isCompatibleAbiVersion -> {
|
!classHeader.isCompatibleAbiVersion -> {
|
||||||
|
|||||||
+10
-10
@@ -44,11 +44,11 @@ import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
|||||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
|
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
|
|
||||||
public open class KotlinClsStubBuilder : ClsStubBuilder() {
|
open class KotlinClsStubBuilder : ClsStubBuilder() {
|
||||||
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + 1
|
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + 1
|
||||||
|
|
||||||
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
||||||
val file = content.getFile()
|
val file = content.file
|
||||||
|
|
||||||
if (isKotlinInternalCompiledFile(file)) {
|
if (isKotlinInternalCompiledFile(file)) {
|
||||||
return null
|
return null
|
||||||
@@ -59,9 +59,9 @@ public open class KotlinClsStubBuilder : ClsStubBuilder() {
|
|||||||
|
|
||||||
fun doBuildFileStub(file: VirtualFile): PsiFileStub<KtFile>? {
|
fun doBuildFileStub(file: VirtualFile): PsiFileStub<KtFile>? {
|
||||||
val kotlinBinaryClass = KotlinBinaryClassCache.getKotlinBinaryClass(file)!!
|
val kotlinBinaryClass = KotlinBinaryClassCache.getKotlinBinaryClass(file)!!
|
||||||
val header = kotlinBinaryClass.getClassHeader()
|
val header = kotlinBinaryClass.classHeader
|
||||||
val classId = kotlinBinaryClass.getClassId()
|
val classId = kotlinBinaryClass.classId
|
||||||
val packageFqName = classId.getPackageFqName()
|
val packageFqName = classId.packageFqName
|
||||||
if (!header.isCompatibleAbiVersion) {
|
if (!header.isCompatibleAbiVersion) {
|
||||||
return createIncompatibleAbiVersionFileStub()
|
return createIncompatibleAbiVersionFileStub()
|
||||||
}
|
}
|
||||||
@@ -74,12 +74,12 @@ public open class KotlinClsStubBuilder : ClsStubBuilder() {
|
|||||||
|
|
||||||
val annotationData = header.annotationData
|
val annotationData = header.annotationData
|
||||||
if (annotationData == null) {
|
if (annotationData == null) {
|
||||||
LOG.error("Corrupted kotlin header for file ${file.getName()}")
|
LOG.error("Corrupted kotlin header for file ${file.name}")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val strings = header.strings
|
val strings = header.strings
|
||||||
if (strings == null) {
|
if (strings == null) {
|
||||||
LOG.error("String table not found in file ${file.getName()}")
|
LOG.error("String table not found in file ${file.name}")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return when {
|
return when {
|
||||||
@@ -94,12 +94,12 @@ public open class KotlinClsStubBuilder : ClsStubBuilder() {
|
|||||||
val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable))
|
val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable))
|
||||||
createFileFacadeStub(packageProto, classId.asSingleFqName(), context)
|
createFileFacadeStub(packageProto, classId.asSingleFqName(), context)
|
||||||
}
|
}
|
||||||
else -> throw IllegalStateException("Should have processed " + file.getPath() + " with header $header")
|
else -> throw IllegalStateException("Should have processed " + file.path + " with header $header")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createStubBuilderComponents(file: VirtualFile, packageFqName: FqName): ClsStubBuilderComponents {
|
private fun createStubBuilderComponents(file: VirtualFile, packageFqName: FqName): ClsStubBuilderComponents {
|
||||||
val classFinder = DirectoryBasedClassFinder(file.getParent()!!, packageFqName)
|
val classFinder = DirectoryBasedClassFinder(file.parent!!, packageFqName)
|
||||||
val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG)
|
val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG)
|
||||||
val annotationLoader = AnnotationLoaderForClassFileStubBuilder(classFinder, LoggingErrorReporter(LOG))
|
val annotationLoader = AnnotationLoaderForClassFileStubBuilder(classFinder, LoggingErrorReporter(LOG))
|
||||||
return ClsStubBuilderComponents(classDataFinder, annotationLoader, file)
|
return ClsStubBuilderComponents(classDataFinder, annotationLoader, file)
|
||||||
@@ -127,7 +127,7 @@ class AnnotationLoaderForClassFileStubBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): ClassId =
|
override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): ClassId =
|
||||||
nameResolver.getClassId(proto.getId())
|
nameResolver.getClassId(proto.id)
|
||||||
|
|
||||||
override fun loadConstant(desc: String, initializer: Any) = null
|
override fun loadConstant(desc: String, initializer: Any) = null
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
|||||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
public class AnnotationLoaderForStubBuilderImpl(
|
class AnnotationLoaderForStubBuilderImpl(
|
||||||
private val protocol: SerializerExtensionProtocol
|
private val protocol: SerializerExtensionProtocol
|
||||||
) : AnnotationAndConstantLoader<ClassId, Unit, ClassIdWithTarget> {
|
) : AnnotationAndConstantLoader<ClassId, Unit, ClassIdWithTarget> {
|
||||||
|
|
||||||
|
|||||||
@@ -23,21 +23,21 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.serialization.js.isDefaultPackageMetafile
|
import org.jetbrains.kotlin.serialization.js.isDefaultPackageMetafile
|
||||||
import org.jetbrains.kotlin.serialization.js.isPackageClassFqName
|
import org.jetbrains.kotlin.serialization.js.isPackageClassFqName
|
||||||
|
|
||||||
public object JsMetaFileUtils {
|
object JsMetaFileUtils {
|
||||||
public fun isKotlinJsMetaFile(file: VirtualFile): Boolean = file.getFileType() == KotlinJavaScriptMetaFileType
|
fun isKotlinJsMetaFile(file: VirtualFile): Boolean = file.fileType == KotlinJavaScriptMetaFileType
|
||||||
|
|
||||||
public fun isKotlinJavaScriptInternalCompiledFile(file: VirtualFile): Boolean =
|
fun isKotlinJavaScriptInternalCompiledFile(file: VirtualFile): Boolean =
|
||||||
isKotlinJsMetaFile(file) && file.getNameWithoutExtension().contains('.')
|
isKotlinJsMetaFile(file) && file.nameWithoutExtension.contains('.')
|
||||||
|
|
||||||
public fun getPackageFqName(file: VirtualFile): FqName = getPackageFqName(getRelativeToRootPath(file))
|
fun getPackageFqName(file: VirtualFile): FqName = getPackageFqName(getRelativeToRootPath(file))
|
||||||
|
|
||||||
public fun getClassFqName(file: VirtualFile): FqName = getClassFqName(getRelativeToRootPath(file))
|
fun getClassFqName(file: VirtualFile): FqName = getClassFqName(getRelativeToRootPath(file))
|
||||||
|
|
||||||
public fun getClassId(file: VirtualFile): ClassId = getClassId(getRelativeToRootPath(file))
|
fun getClassId(file: VirtualFile): ClassId = getClassId(getRelativeToRootPath(file))
|
||||||
|
|
||||||
public fun isPackageHeader(file: VirtualFile): Boolean = isPackageHeader(getRelativeToRootPath(file))
|
fun isPackageHeader(file: VirtualFile): Boolean = isPackageHeader(getRelativeToRootPath(file))
|
||||||
|
|
||||||
public fun getModuleDirectory(file: VirtualFile): VirtualFile =
|
fun getModuleDirectory(file: VirtualFile): VirtualFile =
|
||||||
getRoot(file).findChild(getModuleName(getRelativeToRootPath(file)))!!
|
getRoot(file).findChild(getModuleName(getRelativeToRootPath(file)))!!
|
||||||
|
|
||||||
private fun getRelativeToRootPath(file: VirtualFile): String = VfsUtilCore.getRelativePath(file, getRoot(file))!!
|
private fun getRelativeToRootPath(file: VirtualFile): String = VfsUtilCore.getRelativePath(file, getRoot(file))!!
|
||||||
@@ -70,6 +70,6 @@ public object JsMetaFileUtils {
|
|||||||
return classFqName.isPackageClassFqName()
|
return classFqName.isPackageClassFqName()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRoot(file: VirtualFile): VirtualFile = if (file.getParent() == null) file else getRoot(file.getParent())
|
private fun getRoot(file: VirtualFile): VirtualFile = if (file.parent == null) file else getRoot(file.parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
|
|||||||
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializedResourcePaths
|
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializedResourcePaths
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
|
|
||||||
public class KotlinJavaScriptDeserializerForDecompiler(
|
class KotlinJavaScriptDeserializerForDecompiler(
|
||||||
classFile: VirtualFile
|
classFile: VirtualFile
|
||||||
) : DeserializerForDecompilerBase(classFile.parent!!, JsMetaFileUtils.getPackageFqName(classFile)) {
|
) : DeserializerForDecompilerBase(classFile.parent!!, JsMetaFileUtils.getPackageFqName(classFile)) {
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -58,7 +58,7 @@ class KotlinJavaScriptMetaFileDecompiler : ClassFileDecompilers.Full() {
|
|||||||
|
|
||||||
private val decompilerRendererForJS = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() }
|
private val decompilerRendererForJS = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() }
|
||||||
|
|
||||||
public fun buildDecompiledTextFromJsMetadata(
|
fun buildDecompiledTextFromJsMetadata(
|
||||||
classFile: VirtualFile,
|
classFile: VirtualFile,
|
||||||
resolver: ResolverForDecompiler = KotlinJavaScriptDeserializerForDecompiler(classFile)
|
resolver: ResolverForDecompiler = KotlinJavaScriptDeserializerForDecompiler(classFile)
|
||||||
): DecompiledText {
|
): DecompiledText {
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ import com.intellij.openapi.fileTypes.FileType
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
|
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
|
||||||
|
|
||||||
public object KotlinJavaScriptMetaFileType : FileType {
|
object KotlinJavaScriptMetaFileType : FileType {
|
||||||
|
|
||||||
override fun getName() = "KJSM"
|
override fun getName() = "KJSM"
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,7 @@ import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
|
|||||||
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializedResourcePaths
|
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializedResourcePaths
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
|
|
||||||
public class KotlinJavaScriptStubBuilder : ClsStubBuilder() {
|
class KotlinJavaScriptStubBuilder : ClsStubBuilder() {
|
||||||
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + 1
|
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + 1
|
||||||
|
|
||||||
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.psi.KtElement
|
|||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import com.intellij.openapi.project.DumbService
|
import com.intellij.openapi.project.DumbService
|
||||||
|
|
||||||
public 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) =
|
||||||
|
|||||||
+6
-6
@@ -78,7 +78,7 @@ private class ClassClsStubBuilder(
|
|||||||
private val classOrObjectStub = createClassOrObjectStubAndModifierListStub()
|
private val classOrObjectStub = createClassOrObjectStubAndModifierListStub()
|
||||||
|
|
||||||
fun build() {
|
fun build() {
|
||||||
val typeConstraintListData = typeStubBuilder.createTypeParameterListStub(classOrObjectStub, classProto.getTypeParameterList())
|
val typeConstraintListData = typeStubBuilder.createTypeParameterListStub(classOrObjectStub, classProto.typeParameterList)
|
||||||
createConstructorStub()
|
createConstructorStub()
|
||||||
createDelegationSpecifierList()
|
createDelegationSpecifierList()
|
||||||
typeStubBuilder.createTypeConstraintListStub(classOrObjectStub, typeConstraintListData)
|
typeStubBuilder.createTypeConstraintListStub(classOrObjectStub, typeConstraintListData)
|
||||||
@@ -105,7 +105,7 @@ private class ClassClsStubBuilder(
|
|||||||
ProtoBuf.Class.Kind.ANNOTATION_CLASS -> listOf(KtTokens.ANNOTATION_KEYWORD)
|
ProtoBuf.Class.Kind.ANNOTATION_CLASS -> listOf(KtTokens.ANNOTATION_KEYWORD)
|
||||||
else -> listOf<KtModifierKeywordToken>()
|
else -> listOf<KtModifierKeywordToken>()
|
||||||
}
|
}
|
||||||
return createModifierListStubForDeclaration(parent, classProto.getFlags(), relevantFlags, additionalModifiers)
|
return createModifierListStubForDeclaration(parent, classProto.flags, relevantFlags, additionalModifiers)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doCreateClassOrObjectStub(): StubElement<out PsiElement> {
|
private fun doCreateClassOrObjectStub(): StubElement<out PsiElement> {
|
||||||
@@ -115,12 +115,12 @@ private class ClassClsStubBuilder(
|
|||||||
val superTypeRefs = supertypeIds.filterNot {
|
val superTypeRefs = supertypeIds.filterNot {
|
||||||
//TODO: filtering function types should go away
|
//TODO: filtering function types should go away
|
||||||
KotlinBuiltIns.isNumberedFunctionClassFqName(it.asSingleFqName().toUnsafe())
|
KotlinBuiltIns.isNumberedFunctionClassFqName(it.asSingleFqName().toUnsafe())
|
||||||
}.map { it.getShortClassName().ref() }.toTypedArray()
|
}.map { it.shortClassName.ref() }.toTypedArray()
|
||||||
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
|
||||||
@@ -136,7 +136,7 @@ private class ClassClsStubBuilder(
|
|||||||
isTrait = classKind == ProtoBuf.Class.Kind.INTERFACE,
|
isTrait = 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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,7 +222,7 @@ private class ClassClsStubBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createInnerAndNestedClasses(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) {
|
private fun createInnerAndNestedClasses(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) {
|
||||||
classProto.getNestedClassNameList().forEach { id ->
|
classProto.nestedClassNameList.forEach { id ->
|
||||||
val nestedClassName = c.nameResolver.getName(id)
|
val nestedClassName = c.nameResolver.getName(id)
|
||||||
if (nestedClassName != companionObjectName) {
|
if (nestedClassName != companionObjectName) {
|
||||||
val nestedClassId = classId.createNestedClassId(nestedClassName)
|
val nestedClassId = classId.createNestedClassId(nestedClassName)
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ class TypeParametersImpl(
|
|||||||
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.getId(), nameResolver.getName(it.getName())) }.toMap()
|
private val typeParametersById = typeParameterProtos.map { Pair(it.id, nameResolver.getName(it.name)) }.toMap()
|
||||||
|
|
||||||
override fun get(id: Int): Name = typeParametersById[id] ?: parent[id]
|
override fun get(id: Int): Name = typeParametersById[id] ?: parent[id]
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -46,12 +46,12 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
|||||||
val typeReference = KotlinPlaceHolderStubImpl<KtTypeReference>(parent, KtStubElementTypes.TYPE_REFERENCE)
|
val typeReference = KotlinPlaceHolderStubImpl<KtTypeReference>(parent, KtStubElementTypes.TYPE_REFERENCE)
|
||||||
|
|
||||||
val annotations = c.components.annotationLoader.loadTypeAnnotations(type, c.nameResolver).filterNot {
|
val annotations = c.components.annotationLoader.loadTypeAnnotations(type, c.nameResolver).filterNot {
|
||||||
val isTopLevelClass = !it.isNestedClass()
|
val isTopLevelClass = !it.isNestedClass
|
||||||
isTopLevelClass && it.asSingleFqName() in JvmAnnotationNames.ANNOTATIONS_COPIED_TO_TYPES
|
isTopLevelClass && it.asSingleFqName() in JvmAnnotationNames.ANNOTATIONS_COPIED_TO_TYPES
|
||||||
}
|
}
|
||||||
|
|
||||||
val effectiveParent =
|
val effectiveParent =
|
||||||
if (type.getNullable()) KotlinPlaceHolderStubImpl<KtNullableType>(typeReference, KtStubElementTypes.NULLABLE_TYPE)
|
if (type.nullable) KotlinPlaceHolderStubImpl<KtNullableType>(typeReference, KtStubElementTypes.NULLABLE_TYPE)
|
||||||
else typeReference
|
else typeReference
|
||||||
|
|
||||||
fun createTypeParameterStub(name: Name) {
|
fun createTypeParameterStub(name: Name) {
|
||||||
@@ -68,7 +68,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
|||||||
|
|
||||||
private fun createClassReferenceTypeStub(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassId>) {
|
private fun createClassReferenceTypeStub(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassId>) {
|
||||||
if (type.hasFlexibleTypeCapabilitiesId()) {
|
if (type.hasFlexibleTypeCapabilitiesId()) {
|
||||||
val id = c.nameResolver.getString(type.getFlexibleTypeCapabilitiesId())
|
val id = c.nameResolver.getString(type.flexibleTypeCapabilitiesId)
|
||||||
|
|
||||||
if (id == DynamicTypeCapabilities.id) {
|
if (id == DynamicTypeCapabilities.id) {
|
||||||
KotlinPlaceHolderStubImpl<KtDynamicType>(parent, KtStubElementTypes.DYNAMIC_TYPE)
|
KotlinPlaceHolderStubImpl<KtDynamicType>(parent, KtStubElementTypes.DYNAMIC_TYPE)
|
||||||
@@ -78,7 +78,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
|||||||
|
|
||||||
val classId = c.nameResolver.getClassId(type.className)
|
val classId = c.nameResolver.getClassId(type.className)
|
||||||
val shouldBuildAsFunctionType = KotlinBuiltIns.isNumberedFunctionClassFqName(classId.asSingleFqName().toUnsafe())
|
val shouldBuildAsFunctionType = KotlinBuiltIns.isNumberedFunctionClassFqName(classId.asSingleFqName().toUnsafe())
|
||||||
&& type.getArgumentList().none { it.getProjection() == Projection.STAR }
|
&& type.argumentList.none { it.projection == Projection.STAR }
|
||||||
if (shouldBuildAsFunctionType) {
|
if (shouldBuildAsFunctionType) {
|
||||||
val extension = annotations.any { annotation ->
|
val extension = annotations.any { annotation ->
|
||||||
val fqName = annotation.asSingleFqName()
|
val fqName = annotation.asSingleFqName()
|
||||||
@@ -233,11 +233,11 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
|||||||
typeParameterProto: ProtoBuf.TypeParameter
|
typeParameterProto: ProtoBuf.TypeParameter
|
||||||
) {
|
) {
|
||||||
val modifiers = ArrayList<KtModifierKeywordToken>()
|
val modifiers = ArrayList<KtModifierKeywordToken>()
|
||||||
when (typeParameterProto.getVariance()) {
|
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)
|
||||||
}
|
}
|
||||||
if (typeParameterProto.getReified()) {
|
if (typeParameterProto.reified) {
|
||||||
modifiers.add(KtTokens.REIFIED_KEYWORD)
|
modifiers.add(KtTokens.REIFIED_KEYWORD)
|
||||||
}
|
}
|
||||||
createModifierListStub(typeParameterStub, modifiers)
|
createModifierListStub(typeParameterStub, modifiers)
|
||||||
|
|||||||
+2
-2
@@ -137,7 +137,7 @@ fun createStubForTypeName(
|
|||||||
onUserTypeLevel: (KotlinUserTypeStub, Int) -> Unit = { x, y -> }
|
onUserTypeLevel: (KotlinUserTypeStub, Int) -> Unit = { x, y -> }
|
||||||
): KotlinUserTypeStub {
|
): KotlinUserTypeStub {
|
||||||
val fqName =
|
val fqName =
|
||||||
if (typeClassId.isLocal()) KotlinBuiltIns.FQ_NAMES.any
|
if (typeClassId.isLocal) 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())
|
||||||
@@ -288,7 +288,7 @@ fun createTargetedAnnotationStubs(
|
|||||||
val (annotationClassId, target) = annotation
|
val (annotationClassId, target) = annotation
|
||||||
val annotationEntryStubImpl = KotlinAnnotationEntryStubImpl(
|
val annotationEntryStubImpl = KotlinAnnotationEntryStubImpl(
|
||||||
parent,
|
parent,
|
||||||
shortName = annotationClassId.getShortClassName().ref(),
|
shortName = annotationClassId.shortClassName.ref(),
|
||||||
hasValueArguments = false
|
hasValueArguments = false
|
||||||
)
|
)
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
|
|||||||
+7
-7
@@ -38,11 +38,11 @@ private val descriptorRendererForKeys = DescriptorRenderer.COMPACT_WITH_MODIFIER
|
|||||||
modifiers = DescriptorRendererModifier.ALL
|
modifiers = DescriptorRendererModifier.ALL
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun descriptorToKey(descriptor: DeclarationDescriptor): String {
|
fun descriptorToKey(descriptor: DeclarationDescriptor): String {
|
||||||
return descriptorRendererForKeys.render(descriptor)
|
return descriptorRendererForKeys.render(descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
public data class DecompiledText(public val text: String, public val renderedDescriptorsToRange: Map<String, TextRange>)
|
data class DecompiledText(val text: String, val renderedDescriptorsToRange: Map<String, TextRange>)
|
||||||
|
|
||||||
fun DescriptorRendererOptions.defaultDecompilerRendererOptions() {
|
fun DescriptorRendererOptions.defaultDecompilerRendererOptions() {
|
||||||
withDefinedIn = false
|
withDefinedIn = false
|
||||||
@@ -53,7 +53,7 @@ fun DescriptorRendererOptions.defaultDecompilerRendererOptions() {
|
|||||||
alwaysRenderModifiers = true
|
alwaysRenderModifiers = true
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun buildDecompiledText(
|
fun buildDecompiledText(
|
||||||
packageFqName: FqName,
|
packageFqName: FqName,
|
||||||
descriptors: List<DeclarationDescriptor>,
|
descriptors: List<DeclarationDescriptor>,
|
||||||
descriptorRenderer: DescriptorRenderer
|
descriptorRenderer: DescriptorRenderer
|
||||||
@@ -64,7 +64,7 @@ public fun buildDecompiledText(
|
|||||||
fun appendDecompiledTextAndPackageName() {
|
fun appendDecompiledTextAndPackageName() {
|
||||||
builder.append("// IntelliJ API Decompiler stub source generated from a class file\n" + "// Implementation of methods is not available")
|
builder.append("// IntelliJ API Decompiler stub source generated from a class file\n" + "// Implementation of methods is not available")
|
||||||
builder.append("\n\n")
|
builder.append("\n\n")
|
||||||
if (!packageFqName.isRoot()) {
|
if (!packageFqName.isRoot) {
|
||||||
builder.append("package ").append(packageFqName).append("\n\n")
|
builder.append("package ").append(packageFqName).append("\n\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ public fun buildDecompiledText(
|
|||||||
|
|
||||||
fun appendDescriptor(descriptor: DeclarationDescriptor, indent: String, lastEnumEntry: Boolean? = null) {
|
fun appendDescriptor(descriptor: DeclarationDescriptor, indent: String, lastEnumEntry: Boolean? = null) {
|
||||||
if (descriptor is MissingDependencyErrorClass) {
|
if (descriptor is MissingDependencyErrorClass) {
|
||||||
throw IllegalStateException("${descriptor.javaClass.getSimpleName()} cannot be rendered. FqName: ${descriptor.fullFqName}")
|
throw IllegalStateException("${descriptor.javaClass.simpleName} cannot be rendered. FqName: ${descriptor.fullFqName}")
|
||||||
}
|
}
|
||||||
val startOffset = builder.length
|
val startOffset = builder.length
|
||||||
if (isEnumEntry(descriptor)) {
|
if (isEnumEntry(descriptor)) {
|
||||||
@@ -93,13 +93,13 @@ public fun buildDecompiledText(
|
|||||||
|
|
||||||
if (descriptor is CallableDescriptor) {
|
if (descriptor is CallableDescriptor) {
|
||||||
//NOTE: assuming that only return types can be flexible
|
//NOTE: assuming that only return types can be flexible
|
||||||
if (descriptor.getReturnType()!!.isFlexible()) {
|
if (descriptor.returnType!!.isFlexible()) {
|
||||||
builder.append(" ").append(FLEXIBLE_TYPE_COMMENT)
|
builder.append(" ").append(FLEXIBLE_TYPE_COMMENT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor is FunctionDescriptor || descriptor is PropertyDescriptor) {
|
if (descriptor is FunctionDescriptor || descriptor is PropertyDescriptor) {
|
||||||
if ((descriptor as MemberDescriptor).getModality() != Modality.ABSTRACT) {
|
if ((descriptor as MemberDescriptor).modality != Modality.ABSTRACT) {
|
||||||
if (descriptor is FunctionDescriptor) {
|
if (descriptor is FunctionDescriptor) {
|
||||||
builder.append(" { ").append(DECOMPILED_CODE_COMMENT).append(" }")
|
builder.append(" { ").append(DECOMPILED_CODE_COMMENT).append(" }")
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
|||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
|
|
||||||
public abstract class DeserializerForDecompilerBase(
|
abstract class DeserializerForDecompilerBase(
|
||||||
val packageDirectory: VirtualFile,
|
val packageDirectory: VirtualFile,
|
||||||
val directoryPackageFqName: FqName
|
val directoryPackageFqName: FqName
|
||||||
) : ResolverForDecompiler {
|
) : ResolverForDecompiler {
|
||||||
|
|||||||
+3
-3
@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
public interface ResolverForDecompiler {
|
interface ResolverForDecompiler {
|
||||||
public fun resolveTopLevelClass(classId: ClassId): ClassDescriptor?
|
fun resolveTopLevelClass(classId: ClassId): ClassDescriptor?
|
||||||
|
|
||||||
public fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor>
|
fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor>
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -74,7 +74,7 @@ private class MissingDependencyErrorClassDescriptor(
|
|||||||
init {
|
init {
|
||||||
val emptyConstructor = ConstructorDescriptorImpl.create(this, Annotations.EMPTY, true, SourceElement.NO_SOURCE)
|
val emptyConstructor = ConstructorDescriptorImpl.create(this, Annotations.EMPTY, true, SourceElement.NO_SOURCE)
|
||||||
emptyConstructor.initialize(listOf(), Visibilities.DEFAULT_VISIBILITY)
|
emptyConstructor.initialize(listOf(), Visibilities.DEFAULT_VISIBILITY)
|
||||||
emptyConstructor.setReturnType(createErrorType("<ERROR RETURN TYPE>"))
|
emptyConstructor.returnType = createErrorType("<ERROR RETURN TYPE>")
|
||||||
initialize(MemberScope.Empty, setOf(emptyConstructor), emptyConstructor)
|
initialize(MemberScope.Empty, setOf(emptyConstructor), emptyConstructor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-9
@@ -21,20 +21,20 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.psi.PsiNamedElement
|
import com.intellij.psi.PsiNamedElement
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
|
||||||
public class KotlinFindUsagesProvider : FindUsagesProvider {
|
class KotlinFindUsagesProvider : FindUsagesProvider {
|
||||||
public override fun canFindUsagesFor(psiElement: PsiElement): Boolean =
|
override fun canFindUsagesFor(psiElement: PsiElement): Boolean =
|
||||||
psiElement is KtNamedDeclaration
|
psiElement is KtNamedDeclaration
|
||||||
|
|
||||||
public override fun getWordsScanner() = null
|
override fun getWordsScanner() = null
|
||||||
|
|
||||||
public override fun getHelpId(psiElement: PsiElement): String? = null
|
override fun getHelpId(psiElement: PsiElement): String? = null
|
||||||
|
|
||||||
public override fun getType(element: PsiElement): String {
|
override fun getType(element: PsiElement): String {
|
||||||
return when(element) {
|
return when(element) {
|
||||||
is KtNamedFunction -> "function"
|
is KtNamedFunction -> "function"
|
||||||
is KtClass -> "class"
|
is KtClass -> "class"
|
||||||
is KtParameter -> "parameter"
|
is KtParameter -> "parameter"
|
||||||
is KtProperty -> if (element.isLocal()) "variable" else "property"
|
is KtProperty -> if (element.isLocal) "variable" else "property"
|
||||||
is KtDestructuringDeclarationEntry -> "variable"
|
is KtDestructuringDeclarationEntry -> "variable"
|
||||||
is KtTypeParameter -> "type parameter"
|
is KtTypeParameter -> "type parameter"
|
||||||
is KtSecondaryConstructor -> "constructor"
|
is KtSecondaryConstructor -> "constructor"
|
||||||
@@ -43,10 +43,10 @@ public class KotlinFindUsagesProvider : FindUsagesProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun getDescriptiveName(element: PsiElement): String {
|
override fun getDescriptiveName(element: PsiElement): String {
|
||||||
return if (element is PsiNamedElement) element.getName() ?: "<unnamed>" else ""
|
return if (element is PsiNamedElement) element.name ?: "<unnamed>" else ""
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun getNodeText(element: PsiElement, useFullName: Boolean): String =
|
override fun getNodeText(element: PsiElement, useFullName: Boolean): String =
|
||||||
getDescriptiveName(element)
|
getDescriptiveName(element)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
|
||||||
public object UsageTypeUtils {
|
object UsageTypeUtils {
|
||||||
public fun getUsageType(element: PsiElement?): UsageTypeEnum? {
|
fun getUsageType(element: PsiElement?): UsageTypeEnum? {
|
||||||
when (element) {
|
when (element) {
|
||||||
is KtForExpression -> return IMPLICIT_ITERATION
|
is KtForExpression -> return IMPLICIT_ITERATION
|
||||||
is KtDestructuringDeclaration -> return READ
|
is KtDestructuringDeclaration -> return READ
|
||||||
@@ -48,7 +48,7 @@ public object UsageTypeUtils {
|
|||||||
return when {
|
return when {
|
||||||
refExpr.getNonStrictParentOfType<KtImportDirective>() != null ->
|
refExpr.getNonStrictParentOfType<KtImportDirective>() != null ->
|
||||||
CLASS_IMPORT
|
CLASS_IMPORT
|
||||||
refExpr.getParentOfTypeAndBranch<KtCallableReferenceExpression>(){ getCallableReference() } != null ->
|
refExpr.getParentOfTypeAndBranch<KtCallableReferenceExpression>(){ callableReference } != null ->
|
||||||
CALLABLE_REFERENCE
|
CALLABLE_REFERENCE
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
@@ -60,10 +60,10 @@ public object UsageTypeUtils {
|
|||||||
val property = refExpr.getNonStrictParentOfType<KtProperty>()
|
val property = refExpr.getNonStrictParentOfType<KtProperty>()
|
||||||
if (property != null) {
|
if (property != null) {
|
||||||
when {
|
when {
|
||||||
property.getTypeReference().isAncestor(refExpr) ->
|
property.typeReference.isAncestor(refExpr) ->
|
||||||
return if (property.isLocal()) CLASS_LOCAL_VAR_DECLARATION else NON_LOCAL_PROPERTY_TYPE
|
return if (property.isLocal) CLASS_LOCAL_VAR_DECLARATION else NON_LOCAL_PROPERTY_TYPE
|
||||||
|
|
||||||
property.getReceiverTypeReference().isAncestor(refExpr) ->
|
property.receiverTypeReference.isAncestor(refExpr) ->
|
||||||
return EXTENSION_RECEIVER_TYPE
|
return EXTENSION_RECEIVER_TYPE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,48 +71,48 @@ public object UsageTypeUtils {
|
|||||||
val function = refExpr.getNonStrictParentOfType<KtFunction>()
|
val function = refExpr.getNonStrictParentOfType<KtFunction>()
|
||||||
if (function != null) {
|
if (function != null) {
|
||||||
when {
|
when {
|
||||||
function.getTypeReference().isAncestor(refExpr) ->
|
function.typeReference.isAncestor(refExpr) ->
|
||||||
return FUNCTION_RETURN_TYPE
|
return FUNCTION_RETURN_TYPE
|
||||||
function.getReceiverTypeReference().isAncestor(refExpr) ->
|
function.receiverTypeReference.isAncestor(refExpr) ->
|
||||||
return EXTENSION_RECEIVER_TYPE
|
return EXTENSION_RECEIVER_TYPE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
refExpr.getParentOfTypeAndBranch<KtTypeParameter>(){ getExtendsBound() } != null
|
refExpr.getParentOfTypeAndBranch<KtTypeParameter>(){ extendsBound } != null
|
||||||
|| refExpr.getParentOfTypeAndBranch<KtTypeConstraint>(){ getBoundTypeReference() } != null ->
|
|| refExpr.getParentOfTypeAndBranch<KtTypeConstraint>(){ boundTypeReference } != null ->
|
||||||
TYPE_CONSTRAINT
|
TYPE_CONSTRAINT
|
||||||
|
|
||||||
refExpr is KtSuperTypeListEntry
|
refExpr is KtSuperTypeListEntry
|
||||||
|| refExpr.getParentOfTypeAndBranch<KtSuperTypeListEntry>(){ getTypeReference() } != null ->
|
|| refExpr.getParentOfTypeAndBranch<KtSuperTypeListEntry>(){ typeReference } != null ->
|
||||||
SUPER_TYPE
|
SUPER_TYPE
|
||||||
|
|
||||||
refExpr.getParentOfTypeAndBranch<KtTypedef>(){ getTypeReference() } != null ->
|
refExpr.getParentOfTypeAndBranch<KtTypedef>(){ typeReference } != null ->
|
||||||
TYPE_DEFINITION
|
TYPE_DEFINITION
|
||||||
|
|
||||||
refExpr.getParentOfTypeAndBranch<KtParameter>(){ getTypeReference() } != null ->
|
refExpr.getParentOfTypeAndBranch<KtParameter>(){ typeReference } != null ->
|
||||||
VALUE_PARAMETER_TYPE
|
VALUE_PARAMETER_TYPE
|
||||||
|
|
||||||
refExpr.getParentOfTypeAndBranch<KtIsExpression>(){ getTypeReference() } != null
|
refExpr.getParentOfTypeAndBranch<KtIsExpression>(){ typeReference } != null
|
||||||
|| refExpr.getParentOfTypeAndBranch<KtWhenConditionIsPattern>(){ getTypeReference() } != null ->
|
|| refExpr.getParentOfTypeAndBranch<KtWhenConditionIsPattern>(){ typeReference } != null ->
|
||||||
IS
|
IS
|
||||||
|
|
||||||
with(refExpr.getParentOfTypeAndBranch<KtBinaryExpressionWithTypeRHS>(){ getRight() }) {
|
with(refExpr.getParentOfTypeAndBranch<KtBinaryExpressionWithTypeRHS>(){ right }) {
|
||||||
val opType = this?.getOperationReference()?.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>()) {
|
||||||
if (this == null) false
|
if (this == null) false
|
||||||
else if (getReceiverExpression() == refExpr) true
|
else if (receiverExpression == refExpr) true
|
||||||
else
|
else
|
||||||
getSelectorExpression() == refExpr
|
selectorExpression == refExpr
|
||||||
&& getParentOfTypeAndBranch<KtDotQualifiedExpression>(strict = true) { getReceiverExpression() } != null
|
&& getParentOfTypeAndBranch<KtDotQualifiedExpression>(strict = true) { receiverExpression } != null
|
||||||
} ->
|
} ->
|
||||||
CLASS_OBJECT_ACCESS
|
CLASS_OBJECT_ACCESS
|
||||||
|
|
||||||
refExpr.getParentOfTypeAndBranch<KtSuperExpression>(){ getSuperTypeQualifier() } != null ->
|
refExpr.getParentOfTypeAndBranch<KtSuperExpression>(){ superTypeQualifier } != null ->
|
||||||
SUPER_TYPE_QUALIFIER
|
SUPER_TYPE_QUALIFIER
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
@@ -120,21 +120,21 @@ public object UsageTypeUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getVariableUsageType(): UsageTypeEnum? {
|
fun getVariableUsageType(): UsageTypeEnum? {
|
||||||
if (refExpr.getParentOfTypeAndBranch<KtDelegatedSuperTypeEntry>(){ getDelegateExpression() } != null) {
|
if (refExpr.getParentOfTypeAndBranch<KtDelegatedSuperTypeEntry>(){ delegateExpression } != null) {
|
||||||
return DELEGATE
|
return DELEGATE
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refExpr.getParent() is KtValueArgumentName) return NAMED_ARGUMENT
|
if (refExpr.parent is KtValueArgumentName) return NAMED_ARGUMENT
|
||||||
|
|
||||||
val dotQualifiedExpression = refExpr.getNonStrictParentOfType<KtDotQualifiedExpression>()
|
val dotQualifiedExpression = refExpr.getNonStrictParentOfType<KtDotQualifiedExpression>()
|
||||||
|
|
||||||
if (dotQualifiedExpression != null) {
|
if (dotQualifiedExpression != null) {
|
||||||
val parent = dotQualifiedExpression.getParent()
|
val parent = dotQualifiedExpression.parent
|
||||||
when {
|
when {
|
||||||
dotQualifiedExpression.getReceiverExpression().isAncestor(refExpr) ->
|
dotQualifiedExpression.receiverExpression.isAncestor(refExpr) ->
|
||||||
return RECEIVER
|
return RECEIVER
|
||||||
|
|
||||||
parent is KtDotQualifiedExpression && parent.getReceiverExpression().isAncestor(refExpr) ->
|
parent is KtDotQualifiedExpression && parent.receiverExpression.isAncestor(refExpr) ->
|
||||||
return RECEIVER
|
return RECEIVER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,21 +158,21 @@ public object UsageTypeUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
refExpr.getParentOfTypeAndBranch<KtSuperTypeListEntry>(){ getTypeReference() } != null ->
|
refExpr.getParentOfTypeAndBranch<KtSuperTypeListEntry>(){ typeReference } != null ->
|
||||||
SUPER_TYPE
|
SUPER_TYPE
|
||||||
|
|
||||||
descriptor is ConstructorDescriptor
|
descriptor is ConstructorDescriptor
|
||||||
&& refExpr.getParentOfTypeAndBranch<KtAnnotationEntry>(){ getTypeReference() } != null ->
|
&& refExpr.getParentOfTypeAndBranch<KtAnnotationEntry>(){ typeReference } != null ->
|
||||||
ANNOTATION
|
ANNOTATION
|
||||||
|
|
||||||
with(refExpr.getParentOfTypeAndBranch<KtCallExpression>(){ getCalleeExpression() }) {
|
with(refExpr.getParentOfTypeAndBranch<KtCallExpression>(){ calleeExpression }) {
|
||||||
this?.getCalleeExpression() 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>(){ getOperationReference() } != null ||
|
refExpr.getParentOfTypeAndBranch<KtBinaryExpression>(){ operationReference } != null ||
|
||||||
refExpr.getParentOfTypeAndBranch<KtUnaryExpression>(){ getOperationReference() } != null ||
|
refExpr.getParentOfTypeAndBranch<KtUnaryExpression>(){ operationReference } != null ||
|
||||||
refExpr.getParentOfTypeAndBranch<KtWhenConditionInRange>(){ getOperationReference() } != null ->
|
refExpr.getParentOfTypeAndBranch<KtWhenConditionInRange>(){ operationReference } != null ->
|
||||||
FUNCTION_CALL
|
FUNCTION_CALL
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
|
|||||||
+6
-8
@@ -26,13 +26,11 @@ import org.jetbrains.kotlin.idea.caches.JarUserDataManager
|
|||||||
import org.jetbrains.kotlin.js.JavaScript
|
import org.jetbrains.kotlin.js.JavaScript
|
||||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
||||||
|
|
||||||
public object KotlinJavaScriptLibraryDetectionUtil {
|
object KotlinJavaScriptLibraryDetectionUtil {
|
||||||
@JvmStatic
|
@JvmStatic fun isKotlinJavaScriptLibrary(library: Library): Boolean =
|
||||||
public fun isKotlinJavaScriptLibrary(library: Library): Boolean =
|
|
||||||
isKotlinJavaScriptLibrary(library.getFiles(OrderRootType.CLASSES).toList())
|
isKotlinJavaScriptLibrary(library.getFiles(OrderRootType.CLASSES).toList())
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic fun isKotlinJavaScriptLibrary(classesRoots: List<VirtualFile>): Boolean {
|
||||||
public fun isKotlinJavaScriptLibrary(classesRoots: List<VirtualFile>): Boolean {
|
|
||||||
// Prevent clashing with java runtime
|
// Prevent clashing with java runtime
|
||||||
if (JavaRuntimeDetectionUtil.getJavaRuntimeVersion(classesRoots) != null) return false
|
if (JavaRuntimeDetectionUtil.getJavaRuntimeVersion(classesRoots) != null) return false
|
||||||
|
|
||||||
@@ -51,11 +49,11 @@ public object KotlinJavaScriptLibraryDetectionUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun isJsFileWithMetadata(file: VirtualFile): Boolean =
|
private fun isJsFileWithMetadata(file: VirtualFile): Boolean =
|
||||||
!file.isDirectory() &&
|
!file.isDirectory &&
|
||||||
JavaScript.EXTENSION == file.getExtension() &&
|
JavaScript.EXTENSION == file.extension &&
|
||||||
KotlinJavascriptMetadataUtils.hasMetadata(String(file.contentsToByteArray(false)))
|
KotlinJavascriptMetadataUtils.hasMetadata(String(file.contentsToByteArray(false)))
|
||||||
|
|
||||||
public object HasKotlinJSMetadataInJar : JarUserDataManager.JarBooleanPropertyCounter(HasKotlinJSMetadataInJar::class.simpleName!!) {
|
object HasKotlinJSMetadataInJar : JarUserDataManager.JarBooleanPropertyCounter(HasKotlinJSMetadataInJar::class.simpleName!!) {
|
||||||
override fun hasProperty(file: VirtualFile) = KotlinJavaScriptLibraryDetectionUtil.isJsFileWithMetadata(file)
|
override fun hasProperty(file: VirtualFile) = KotlinJavaScriptLibraryDetectionUtil.isJsFileWithMetadata(file)
|
||||||
|
|
||||||
fun hasMetadataFromCache(root: VirtualFile): Boolean? = JarUserDataManager.hasFileWithProperty(HasKotlinJSMetadataInJar, root)
|
fun hasMetadataFromCache(root: VirtualFile): Boolean? = JarUserDataManager.hasFileWithProperty(HasKotlinJSMetadataInJar, root)
|
||||||
|
|||||||
@@ -27,65 +27,55 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
public object IdeRenderers {
|
object IdeRenderers {
|
||||||
|
|
||||||
@JvmField
|
@JvmField val HTML_AMBIGUOUS_CALLS: Renderer<Collection<ResolvedCall<*>>> = Renderer {
|
||||||
public val HTML_AMBIGUOUS_CALLS: Renderer<Collection<ResolvedCall<*>>> = Renderer {
|
|
||||||
calls: Collection<ResolvedCall<*>> ->
|
calls: Collection<ResolvedCall<*>> ->
|
||||||
calls
|
calls
|
||||||
.map { it.getResultingDescriptor() }
|
.map { it.resultingDescriptor }
|
||||||
.sortedWith(MemberComparator.INSTANCE)
|
.sortedWith(MemberComparator.INSTANCE)
|
||||||
.joinToString("") { "<li>" + DescriptorRenderer.HTML.render(it) + "</li>" }
|
.joinToString("") { "<li>" + DescriptorRenderer.HTML.render(it) + "</li>" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField val HTML_RENDER_TYPE: Renderer<KotlinType> = Renderer {
|
||||||
public val HTML_RENDER_TYPE: Renderer<KotlinType> = Renderer {
|
|
||||||
DescriptorRenderer.HTML.renderType(it)
|
DescriptorRenderer.HTML.renderType(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField val HTML_NONE_APPLICABLE_CALLS: Renderer<Collection<ResolvedCall<*>>> = Renderer {
|
||||||
public val HTML_NONE_APPLICABLE_CALLS: Renderer<Collection<ResolvedCall<*>>> = Renderer {
|
|
||||||
calls: Collection<ResolvedCall<*>> ->
|
calls: Collection<ResolvedCall<*>> ->
|
||||||
// TODO: compareBy(comparator, selector) in stdlib
|
// TODO: compareBy(comparator, selector) in stdlib
|
||||||
val comparator = comparator<ResolvedCall<*>> { c1, c2 -> MemberComparator.INSTANCE.compare(c1.getResultingDescriptor(), c2.getResultingDescriptor()) }
|
val comparator = comparator<ResolvedCall<*>> { c1, c2 -> MemberComparator.INSTANCE.compare(c1.resultingDescriptor, c2.resultingDescriptor) }
|
||||||
calls
|
calls
|
||||||
.sortedWith(comparator)
|
.sortedWith(comparator)
|
||||||
.joinToString("") { "<li>" + renderResolvedCall(it) + "</li>" }
|
.joinToString("") { "<li>" + renderResolvedCall(it) + "</li>" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField val HTML_TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER: Renderer<InferenceErrorData> = Renderer {
|
||||||
public val HTML_TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER: Renderer<InferenceErrorData> = Renderer {
|
|
||||||
Renderers.renderConflictingSubstitutionsInferenceError(it, HtmlTabledDescriptorRenderer.create()).toString()
|
Renderers.renderConflictingSubstitutionsInferenceError(it, HtmlTabledDescriptorRenderer.create()).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField val HTML_TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR_RENDERER: Renderer<InferenceErrorData> = Renderer {
|
||||||
public val HTML_TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR_RENDERER: Renderer<InferenceErrorData> = Renderer {
|
|
||||||
Renderers.renderParameterConstraintError(it, HtmlTabledDescriptorRenderer.create()).toString()
|
Renderers.renderParameterConstraintError(it, HtmlTabledDescriptorRenderer.create()).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField val HTML_TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER: Renderer<InferenceErrorData> = Renderer {
|
||||||
public val HTML_TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER: Renderer<InferenceErrorData> = Renderer {
|
|
||||||
Renderers.renderNoInformationForParameterError(it, HtmlTabledDescriptorRenderer.create()).toString()
|
Renderers.renderNoInformationForParameterError(it, HtmlTabledDescriptorRenderer.create()).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField val HTML_TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER: Renderer<InferenceErrorData> = Renderer {
|
||||||
public val HTML_TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER: Renderer<InferenceErrorData> = Renderer {
|
|
||||||
Renderers.renderUpperBoundViolatedInferenceError(it, HtmlTabledDescriptorRenderer.create()).toString()
|
Renderers.renderUpperBoundViolatedInferenceError(it, HtmlTabledDescriptorRenderer.create()).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField val HTML_RENDER_RETURN_TYPE: Renderer<CallableMemberDescriptor> = Renderer {
|
||||||
public val HTML_RENDER_RETURN_TYPE: Renderer<CallableMemberDescriptor> = Renderer {
|
val returnType = it.returnType!!
|
||||||
val returnType = it.getReturnType()!!
|
|
||||||
DescriptorRenderer.HTML.renderType(returnType)
|
DescriptorRenderer.HTML.renderType(returnType)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField val HTML_COMPACT_WITH_MODIFIERS: DescriptorRenderer = DescriptorRenderer.HTML.withOptions {
|
||||||
public val HTML_COMPACT_WITH_MODIFIERS: DescriptorRenderer = DescriptorRenderer.HTML.withOptions {
|
|
||||||
withDefinedIn = false
|
withDefinedIn = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField val HTML_CONFLICTING_JVM_DECLARATIONS_DATA: Renderer<ConflictingJvmDeclarationsData> = Renderer {
|
||||||
public val HTML_CONFLICTING_JVM_DECLARATIONS_DATA: Renderer<ConflictingJvmDeclarationsData> = Renderer {
|
|
||||||
data: ConflictingJvmDeclarationsData ->
|
data: ConflictingJvmDeclarationsData ->
|
||||||
|
|
||||||
val conflicts = data.signatureOrigins
|
val conflicts = data.signatureOrigins
|
||||||
@@ -96,8 +86,7 @@ public object IdeRenderers {
|
|||||||
"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 val HTML_THROWABLE: Renderer<Throwable> = Renderer {
|
||||||
public val HTML_THROWABLE: Renderer<Throwable> = Renderer {
|
|
||||||
Renderers.THROWABLE.render(it).replace("\n", "<br/>")
|
Renderers.THROWABLE.render(it).replace("\n", "<br/>")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -36,7 +36,7 @@ import com.intellij.psi.PsiRecursiveElementVisitor
|
|||||||
import org.jetbrains.kotlin.idea.kdoc.KDocHighlightingVisitor
|
import org.jetbrains.kotlin.idea.kdoc.KDocHighlightingVisitor
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
public 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 {
|
||||||
@@ -68,7 +68,7 @@ public class KotlinBeforeResolveHighlightingPass(
|
|||||||
annotationHolder = null
|
annotationHolder = null
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Factory(project: Project, registrar: TextEditorHighlightingPassRegistrar) : AbstractProjectComponent(project), TextEditorHighlightingPassFactory {
|
class Factory(project: Project, registrar: TextEditorHighlightingPassRegistrar) : AbstractProjectComponent(project), 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)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ import com.intellij.ide.projectView.impl.ProjectRootsUtil
|
|||||||
class KotlinProblemHighlightFilter : ProblemHighlightFilter() {
|
class KotlinProblemHighlightFilter : ProblemHighlightFilter() {
|
||||||
|
|
||||||
override fun shouldHighlight(psiFile: PsiFile): Boolean {
|
override fun shouldHighlight(psiFile: PsiFile): Boolean {
|
||||||
return psiFile.getFileType() != KotlinFileType.INSTANCE || !ProjectRootsUtil.isOutsideSourceRoot(psiFile)
|
return psiFile.fileType != KotlinFileType.INSTANCE || !ProjectRootsUtil.isOutsideSourceRoot(psiFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,12 +54,12 @@ import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
|||||||
import java.lang.reflect.*
|
import java.lang.reflect.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public open class KotlinPsiChecker : Annotator, HighlightRangeExtension {
|
open class KotlinPsiChecker : Annotator, HighlightRangeExtension {
|
||||||
|
|
||||||
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
|
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
|
||||||
if (!(ProjectRootsUtil.isInProjectOrLibraryContent(element) || element.getContainingFile() is KtCodeFragment)) return
|
if (!(ProjectRootsUtil.isInProjectOrLibraryContent(element) || element.containingFile is KtCodeFragment)) return
|
||||||
|
|
||||||
val file = element.getContainingFile() as KtFile
|
val file = element.containingFile as KtFile
|
||||||
|
|
||||||
val analysisResult = file.analyzeFullyAndGetResult()
|
val analysisResult = file.analyzeFullyAndGetResult()
|
||||||
if (analysisResult.isError()) {
|
if (analysisResult.isError()) {
|
||||||
@@ -80,7 +80,7 @@ public open class KotlinPsiChecker : Annotator, HighlightRangeExtension {
|
|||||||
open protected fun shouldSuppressUnusedParameter(parameter: KtParameter): Boolean = false
|
open protected fun shouldSuppressUnusedParameter(parameter: KtParameter): Boolean = false
|
||||||
|
|
||||||
fun annotateElement(element: PsiElement, holder: AnnotationHolder, diagnostics: Diagnostics) {
|
fun annotateElement(element: PsiElement, holder: AnnotationHolder, diagnostics: Diagnostics) {
|
||||||
if (ProjectRootsUtil.isInProjectSource(element) || element.getContainingFile() is KtCodeFragment) {
|
if (ProjectRootsUtil.isInProjectSource(element) || element.containingFile is KtCodeFragment) {
|
||||||
ElementAnnotator(element, holder, { param -> shouldSuppressUnusedParameter(param) }).registerDiagnosticsAnnotations(diagnostics.forElement(element))
|
ElementAnnotator(element, holder, { param -> shouldSuppressUnusedParameter(param) }).registerDiagnosticsAnnotations(diagnostics.forElement(element))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ public open class KotlinPsiChecker : Annotator, HighlightRangeExtension {
|
|||||||
TypeKindHighlightingVisitor(holder, bindingContext)
|
TypeKindHighlightingVisitor(holder, bindingContext)
|
||||||
)
|
)
|
||||||
|
|
||||||
public fun createQuickFixes(diagnostic: Diagnostic): Collection<IntentionAction> =
|
fun createQuickFixes(diagnostic: Diagnostic): Collection<IntentionAction> =
|
||||||
createQuickFixes(diagnostic.singletonOrEmptyList())[diagnostic]
|
createQuickFixes(diagnostic.singletonOrEmptyList())[diagnostic]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@ private fun createQuickFixes(similarDiagnostics: Collection<Diagnostic>): MultiM
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (diagnostic in similarDiagnostics) {
|
for (diagnostic in similarDiagnostics) {
|
||||||
actions.putValues(diagnostic, QuickFixes.getInstance().getActions(diagnostic.getFactory()))
|
actions.putValues(diagnostic, QuickFixes.getInstance().getActions(diagnostic.factory))
|
||||||
}
|
}
|
||||||
|
|
||||||
actions.values().forEach { NoDeclarationDescriptorsChecker.check(it.javaClass) }
|
actions.values().forEach { NoDeclarationDescriptorsChecker.check(it.javaClass) }
|
||||||
@@ -177,9 +177,9 @@ private class ElementAnnotator(private val element: PsiElement,
|
|||||||
if (validDiagnostics.isEmpty()) return
|
if (validDiagnostics.isEmpty()) return
|
||||||
|
|
||||||
val diagnostic = diagnostics.first()
|
val diagnostic = diagnostics.first()
|
||||||
val factory = diagnostic.getFactory()
|
val factory = diagnostic.factory
|
||||||
|
|
||||||
assert(diagnostics.all { it.getPsiElement() == element && it.factory == factory })
|
assert(diagnostics.all { it.psiElement == element && it.factory == factory })
|
||||||
|
|
||||||
val ranges = diagnostic.textRanges
|
val ranges = diagnostic.textRanges
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ private class ElementAnnotator(private val element: PsiElement,
|
|||||||
val reference = referenceExpression.mainReference
|
val reference = referenceExpression.mainReference
|
||||||
if (reference is MultiRangeReference) {
|
if (reference is MultiRangeReference) {
|
||||||
AnnotationPresentationInfo(
|
AnnotationPresentationInfo(
|
||||||
ranges = reference.getRanges().map { it.shiftRight(referenceExpression.getTextOffset()) },
|
ranges = reference.ranges.map { it.shiftRight(referenceExpression.textOffset) },
|
||||||
highlightType = ProblemHighlightType.LIKE_UNKNOWN_SYMBOL)
|
highlightType = ProblemHighlightType.LIKE_UNKNOWN_SYMBOL)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -202,7 +202,7 @@ private class ElementAnnotator(private val element: PsiElement,
|
|||||||
Errors.ILLEGAL_ESCAPE -> AnnotationPresentationInfo(ranges, textAttributes = KotlinHighlightingColors.INVALID_STRING_ESCAPE)
|
Errors.ILLEGAL_ESCAPE -> AnnotationPresentationInfo(ranges, textAttributes = KotlinHighlightingColors.INVALID_STRING_ESCAPE)
|
||||||
|
|
||||||
Errors.REDECLARATION -> AnnotationPresentationInfo(
|
Errors.REDECLARATION -> AnnotationPresentationInfo(
|
||||||
ranges = listOf(diagnostic.getTextRanges().first()), nonDefaultMessage = "")
|
ranges = listOf(diagnostic.textRanges.first()), nonDefaultMessage = "")
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
AnnotationPresentationInfo(
|
AnnotationPresentationInfo(
|
||||||
@@ -243,12 +243,12 @@ private class ElementAnnotator(private val element: PsiElement,
|
|||||||
|
|
||||||
fixes.forEach { annotation.registerFix(it) }
|
fixes.forEach { annotation.registerFix(it) }
|
||||||
|
|
||||||
if (diagnostic.getSeverity() == Severity.WARNING) {
|
if (diagnostic.severity == Severity.WARNING) {
|
||||||
annotation.setProblemGroup(KotlinSuppressableWarningProblemGroup(diagnostic.getFactory()))
|
annotation.problemGroup = KotlinSuppressableWarningProblemGroup(diagnostic.factory)
|
||||||
|
|
||||||
if (fixes.isEmpty()) {
|
if (fixes.isEmpty()) {
|
||||||
// if there are no quick fixes we need to register an EmptyIntentionAction to enable 'suppress' actions
|
// if there are no quick fixes we need to register an EmptyIntentionAction to enable 'suppress' actions
|
||||||
annotation.registerFix(EmptyIntentionAction(diagnostic.getFactory().getName()))
|
annotation.registerFix(EmptyIntentionAction(diagnostic.factory.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,7 +262,7 @@ private class AnnotationPresentationInfo(
|
|||||||
val highlightType: ProblemHighlightType? = null,
|
val highlightType: ProblemHighlightType? = null,
|
||||||
val textAttributes: TextAttributesKey? = null) {
|
val textAttributes: TextAttributesKey? = null) {
|
||||||
|
|
||||||
public fun create(diagnostic: Diagnostic, range: TextRange, holder: AnnotationHolder): Annotation {
|
fun create(diagnostic: Diagnostic, range: TextRange, holder: AnnotationHolder): Annotation {
|
||||||
val defaultMessage = nonDefaultMessage?: getDefaultMessage(diagnostic)
|
val defaultMessage = nonDefaultMessage?: getDefaultMessage(diagnostic)
|
||||||
|
|
||||||
val annotation = when (diagnostic.severity) {
|
val annotation = when (diagnostic.severity) {
|
||||||
@@ -286,8 +286,8 @@ private class AnnotationPresentationInfo(
|
|||||||
|
|
||||||
private fun getMessage(diagnostic: Diagnostic): String {
|
private fun getMessage(diagnostic: Diagnostic): String {
|
||||||
var message = IdeErrorMessages.render(diagnostic)
|
var message = IdeErrorMessages.render(diagnostic)
|
||||||
if (KotlinInternalMode.enabled || ApplicationManager.getApplication().isUnitTestMode()) {
|
if (KotlinInternalMode.enabled || ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
val factoryName = diagnostic.getFactory().getName()
|
val factoryName = diagnostic.factory.name
|
||||||
if (message.startsWith("<html>")) {
|
if (message.startsWith("<html>")) {
|
||||||
message = "<html>[$factoryName] ${message.substring("<html>".length)}"
|
message = "<html>[$factoryName] ${message.substring("<html>".length)}"
|
||||||
}
|
}
|
||||||
@@ -303,8 +303,8 @@ private class AnnotationPresentationInfo(
|
|||||||
|
|
||||||
private fun getDefaultMessage(diagnostic: Diagnostic): String {
|
private fun getDefaultMessage(diagnostic: Diagnostic): String {
|
||||||
val message = DefaultErrorMessages.render(diagnostic)
|
val message = DefaultErrorMessages.render(diagnostic)
|
||||||
if (KotlinInternalMode.enabled || ApplicationManager.getApplication().isUnitTestMode()) {
|
if (KotlinInternalMode.enabled || ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
return "[${diagnostic.getFactory().getName()}] $message"
|
return "[${diagnostic.factory.name}] $message"
|
||||||
}
|
}
|
||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -32,10 +32,10 @@ class KotlinSuppressableWarningProblemGroup(
|
|||||||
) : SuppressableProblemGroup {
|
) : SuppressableProblemGroup {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
assert (diagnosticFactory.getSeverity() == Severity.WARNING)
|
assert (diagnosticFactory.severity == Severity.WARNING)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getProblemName() = diagnosticFactory.getName()
|
override fun getProblemName() = diagnosticFactory.name
|
||||||
|
|
||||||
override fun getSuppressActions(element: PsiElement?): Array<SuppressIntentionAction> {
|
override fun getSuppressActions(element: PsiElement?): Array<SuppressIntentionAction> {
|
||||||
if (element == null)
|
if (element == null)
|
||||||
@@ -99,10 +99,10 @@ private object DeclarationKindDetector : KtVisitor<AnnotationHostKind?, Unit?>()
|
|||||||
|
|
||||||
override fun visitNamedFunction(d: KtNamedFunction, data: Unit?) = detect(d, "fun")
|
override fun visitNamedFunction(d: KtNamedFunction, data: Unit?) = detect(d, "fun")
|
||||||
|
|
||||||
override fun visitProperty(d: KtProperty, data: Unit?) = detect(d, d.getValOrVarKeyword().getText()!!)
|
override fun visitProperty(d: KtProperty, data: Unit?) = detect(d, d.valOrVarKeyword.text!!)
|
||||||
|
|
||||||
override fun visitDestructuringDeclaration(d: KtDestructuringDeclaration, data: Unit?) = detect(d, d.getValOrVarKeyword()?.getText() ?: "val",
|
override fun visitDestructuringDeclaration(d: KtDestructuringDeclaration, data: Unit?) = detect(d, d.valOrVarKeyword?.text ?: "val",
|
||||||
name = d.getEntries().map { it.getName()!! }.joinToString(", ", "(", ")"))
|
name = d.entries.map { it.name!! }.joinToString(", ", "(", ")"))
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
@@ -111,11 +111,11 @@ 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 visitObjectDeclaration(d: KtObjectDeclaration, data: Unit?): AnnotationHostKind? {
|
override fun visitObjectDeclaration(d: KtObjectDeclaration, data: Unit?): AnnotationHostKind? {
|
||||||
if (d.isCompanion()) return detect(d, "companion object", name = "${d.getName()} of ${d.getStrictParentOfType<KtClass>()?.getName()}")
|
if (d.isCompanion()) return detect(d, "companion object", name = "${d.name} of ${d.getStrictParentOfType<KtClass>()?.name}")
|
||||||
if (d.getParent() is KtObjectLiteralExpression) return null
|
if (d.parent is KtObjectLiteralExpression) return null
|
||||||
return detect(d, "object")
|
return detect(d, "object")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun detect(declaration: KtDeclaration, kind: String, name: String = declaration.getName() ?: "<anonymous>", newLineNeeded: Boolean = true)
|
private fun detect(declaration: KtDeclaration, kind: String, name: String = declaration.name ?: "<anonymous>", newLineNeeded: Boolean = true)
|
||||||
= AnnotationHostKind(kind, name, newLineNeeded)
|
= AnnotationHostKind(kind, name, newLineNeeded)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,20 +23,20 @@ import com.intellij.psi.PsiElement
|
|||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
|
|
||||||
object NameHighlighter {
|
object NameHighlighter {
|
||||||
public var namesHighlightingEnabled = true
|
var namesHighlightingEnabled = true
|
||||||
@TestOnly set
|
@TestOnly set
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun highlightName(holder: AnnotationHolder, psiElement: PsiElement, attributesKey: TextAttributesKey) {
|
fun highlightName(holder: AnnotationHolder, psiElement: PsiElement, attributesKey: TextAttributesKey) {
|
||||||
if (namesHighlightingEnabled) {
|
if (namesHighlightingEnabled) {
|
||||||
holder.createInfoAnnotation(psiElement, null).setTextAttributes(attributesKey)
|
holder.createInfoAnnotation(psiElement, null).textAttributes = attributesKey
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun highlightName(holder: AnnotationHolder, textRange: TextRange, attributesKey: TextAttributesKey) {
|
fun highlightName(holder: AnnotationHolder, textRange: TextRange, attributesKey: TextAttributesKey) {
|
||||||
if (namesHighlightingEnabled) {
|
if (namesHighlightingEnabled) {
|
||||||
holder.createInfoAnnotation(textRange, null).setTextAttributes(attributesKey)
|
holder.createInfoAnnotation(textRange, null).textAttributes = attributesKey
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,11 +32,11 @@ import org.jetbrains.kotlin.types.ErrorUtils
|
|||||||
private val RED_TEMPLATE = "<font color=red><b>%s</b></font>"
|
private val RED_TEMPLATE = "<font color=red><b>%s</b></font>"
|
||||||
private val STRONG_TEMPLATE = "<b>%s</b>"
|
private val STRONG_TEMPLATE = "<b>%s</b>"
|
||||||
|
|
||||||
public fun renderStrong(o: Any): String = STRONG_TEMPLATE.format(o)
|
fun renderStrong(o: Any): String = STRONG_TEMPLATE.format(o)
|
||||||
|
|
||||||
public fun renderError(o: Any): String = RED_TEMPLATE.format(o)
|
fun renderError(o: Any): String = RED_TEMPLATE.format(o)
|
||||||
|
|
||||||
public fun renderStrong(o: Any, error: Boolean): String = (if (error) RED_TEMPLATE else STRONG_TEMPLATE).format(o)
|
fun renderStrong(o: Any, error: Boolean): String = (if (error) RED_TEMPLATE else STRONG_TEMPLATE).format(o)
|
||||||
|
|
||||||
private val HTML_FOR_UNINFERRED_TYPE_PARAMS: DescriptorRenderer = DescriptorRenderer.withOptions {
|
private val HTML_FOR_UNINFERRED_TYPE_PARAMS: DescriptorRenderer = DescriptorRenderer.withOptions {
|
||||||
uninferredTypeParameterAsName = true
|
uninferredTypeParameterAsName = true
|
||||||
@@ -54,7 +54,7 @@ fun <D : CallableDescriptor> renderResolvedCall(resolvedCall: ResolvedCall<D>):
|
|||||||
|
|
||||||
fun renderParameter(parameter: ValueParameterDescriptor): String {
|
fun renderParameter(parameter: ValueParameterDescriptor): String {
|
||||||
val varargElementType = parameter.varargElementType
|
val varargElementType = parameter.varargElementType
|
||||||
val parameterType = varargElementType ?: parameter.getType()
|
val parameterType = varargElementType ?: parameter.type
|
||||||
val renderedParameter =
|
val renderedParameter =
|
||||||
(if (varargElementType != null) "<b>vararg</b> " else "") +
|
(if (varargElementType != null) "<b>vararg</b> " else "") +
|
||||||
htmlRenderer.renderType(parameterType) +
|
htmlRenderer.renderType(parameterType) +
|
||||||
@@ -66,50 +66,50 @@ fun <D : CallableDescriptor> renderResolvedCall(resolvedCall: ResolvedCall<D>):
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun appendTypeParametersSubstitution() {
|
fun appendTypeParametersSubstitution() {
|
||||||
val parametersToArgumentsMap = resolvedCall.getTypeArguments()
|
val parametersToArgumentsMap = resolvedCall.typeArguments
|
||||||
fun TypeParameterDescriptor.isInferred(): Boolean {
|
fun TypeParameterDescriptor.isInferred(): Boolean {
|
||||||
val typeArgument = parametersToArgumentsMap[this]
|
val typeArgument = parametersToArgumentsMap[this]
|
||||||
if (typeArgument == null) return false
|
if (typeArgument == null) return false
|
||||||
return !ErrorUtils.isUninferredParameter(typeArgument)
|
return !ErrorUtils.isUninferredParameter(typeArgument)
|
||||||
}
|
}
|
||||||
|
|
||||||
val typeParameters = resolvedCall.getCandidateDescriptor().getTypeParameters()
|
val typeParameters = resolvedCall.candidateDescriptor.typeParameters
|
||||||
val (inferredTypeParameters, notInferredTypeParameters) = typeParameters.partition { parameter -> parameter.isInferred() }
|
val (inferredTypeParameters, notInferredTypeParameters) = typeParameters.partition { parameter -> parameter.isInferred() }
|
||||||
|
|
||||||
append("<br/>$indent<i>where</i> ")
|
append("<br/>$indent<i>where</i> ")
|
||||||
if (!notInferredTypeParameters.isEmpty()) {
|
if (!notInferredTypeParameters.isEmpty()) {
|
||||||
append(notInferredTypeParameters.map { typeParameter -> renderError(typeParameter.getName()) }.joinToString())
|
append(notInferredTypeParameters.map { typeParameter -> renderError(typeParameter.name) }.joinToString())
|
||||||
append("<i> cannot be inferred</i>")
|
append("<i> cannot be inferred</i>")
|
||||||
if (!inferredTypeParameters.isEmpty()) {
|
if (!inferredTypeParameters.isEmpty()) {
|
||||||
append("; ")
|
append("; ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val typeParameterToTypeArgumentMap = resolvedCall.getTypeArguments()
|
val typeParameterToTypeArgumentMap = resolvedCall.typeArguments
|
||||||
if (!inferredTypeParameters.isEmpty()) {
|
if (!inferredTypeParameters.isEmpty()) {
|
||||||
append(inferredTypeParameters.map { typeParameter ->
|
append(inferredTypeParameters.map { typeParameter ->
|
||||||
"${typeParameter.getName()} = ${htmlRenderer.renderType(typeParameterToTypeArgumentMap[typeParameter]!!)}"
|
"${typeParameter.name} = ${htmlRenderer.renderType(typeParameterToTypeArgumentMap[typeParameter]!!)}"
|
||||||
}.joinToString())
|
}.joinToString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val resultingDescriptor = resolvedCall.getResultingDescriptor()
|
val resultingDescriptor = resolvedCall.resultingDescriptor
|
||||||
val receiverParameter = resultingDescriptor.getExtensionReceiverParameter()
|
val receiverParameter = resultingDescriptor.extensionReceiverParameter
|
||||||
if (receiverParameter != null) {
|
if (receiverParameter != null) {
|
||||||
append(htmlRenderer.renderType(receiverParameter.getType())).append(".")
|
append(htmlRenderer.renderType(receiverParameter.type)).append(".")
|
||||||
}
|
}
|
||||||
append(resultingDescriptor.getName()).append("(")
|
append(resultingDescriptor.name).append("(")
|
||||||
append(resultingDescriptor.getValueParameters().map { parameter -> renderParameter(parameter) }.joinToString())
|
append(resultingDescriptor.valueParameters.map { parameter -> renderParameter(parameter) }.joinToString())
|
||||||
append(if (resolvedCall.hasUnmappedArguments()) renderError(")") else ")")
|
append(if (resolvedCall.hasUnmappedArguments()) renderError(")") else ")")
|
||||||
|
|
||||||
if (!resolvedCall.getCandidateDescriptor().getTypeParameters().isEmpty()) {
|
if (!resolvedCall.candidateDescriptor.typeParameters.isEmpty()) {
|
||||||
appendTypeParametersSubstitution()
|
appendTypeParametersSubstitution()
|
||||||
append("<i> for </i><br/>$indent")
|
append("<i> for </i><br/>$indent")
|
||||||
append(htmlRenderer.render(resolvedCall.getCandidateDescriptor()))
|
append(htmlRenderer.render(resolvedCall.candidateDescriptor))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
append(" <i>defined in</i> ")
|
append(" <i>defined in</i> ")
|
||||||
val containingDeclaration = resultingDescriptor.getContainingDeclaration()
|
val containingDeclaration = resultingDescriptor.containingDeclaration
|
||||||
val fqName = DescriptorUtils.getFqName(containingDeclaration)
|
val fqName = DescriptorUtils.getFqName(containingDeclaration)
|
||||||
append(if (fqName.isRoot) "root package" else fqName.asString())
|
append(if (fqName.isRoot) "root package" else fqName.asString())
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -26,15 +26,15 @@ import org.jetbrains.kotlin.diagnostics.Severity
|
|||||||
import org.jetbrains.kotlin.idea.highlighter.createSuppressWarningActions
|
import org.jetbrains.kotlin.idea.highlighter.createSuppressWarningActions
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.KotlinCacheService
|
import org.jetbrains.kotlin.idea.caches.resolve.KotlinCacheService
|
||||||
|
|
||||||
public abstract class AbstractKotlinInspection: LocalInspectionTool(), CustomSuppressableInspectionTool {
|
abstract class AbstractKotlinInspection: LocalInspectionTool(), CustomSuppressableInspectionTool {
|
||||||
public override fun getSuppressActions(element: PsiElement?): Array<SuppressIntentionAction>? {
|
override fun getSuppressActions(element: PsiElement?): Array<SuppressIntentionAction>? {
|
||||||
if (element == null) return emptyArray()
|
if (element == null) return emptyArray()
|
||||||
|
|
||||||
return createSuppressWarningActions(element, toSeverity(defaultLevel), suppressionKey).toTypedArray()
|
return createSuppressWarningActions(element, toSeverity(defaultLevel), suppressionKey).toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun isSuppressedFor(element: PsiElement): Boolean {
|
override fun isSuppressedFor(element: PsiElement): Boolean {
|
||||||
if (SuppressManager.getInstance()!!.isSuppressedFor(element, getID())) {
|
if (SuppressManager.getInstance()!!.isSuppressedFor(element, id)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -34,8 +34,8 @@ import com.intellij.util.SmartList
|
|||||||
import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
|
import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
|
||||||
public abstract class IntentionBasedInspection<TElement : KtElement>(
|
abstract class IntentionBasedInspection<TElement : KtElement>(
|
||||||
public val intentions: List<IntentionBasedInspection.IntentionData<TElement>>,
|
val intentions: List<IntentionBasedInspection.IntentionData<TElement>>,
|
||||||
protected val problemText: String?,
|
protected val problemText: String?,
|
||||||
protected val elementType: Class<TElement>
|
protected val elementType: Class<TElement>
|
||||||
) : AbstractKotlinInspection() {
|
) : AbstractKotlinInspection() {
|
||||||
@@ -43,7 +43,7 @@ public abstract class IntentionBasedInspection<TElement : KtElement>(
|
|||||||
constructor(intention: SelfTargetingRangeIntention<TElement>, additionalChecker: (TElement) -> Boolean = { true })
|
constructor(intention: SelfTargetingRangeIntention<TElement>, additionalChecker: (TElement) -> Boolean = { true })
|
||||||
: this(listOf(IntentionData(intention, additionalChecker)), null, intention.elementType)
|
: this(listOf(IntentionData(intention, additionalChecker)), null, intention.elementType)
|
||||||
|
|
||||||
public data class IntentionData<TElement : KtElement>(
|
data class IntentionData<TElement : KtElement>(
|
||||||
val intention: SelfTargetingRangeIntention<TElement>,
|
val intention: SelfTargetingRangeIntention<TElement>,
|
||||||
val additionalChecker: (TElement) -> Boolean = { true }
|
val additionalChecker: (TElement) -> Boolean = { true }
|
||||||
)
|
)
|
||||||
@@ -51,7 +51,7 @@ public abstract class IntentionBasedInspection<TElement : KtElement>(
|
|||||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
|
||||||
return object : PsiElementVisitor() {
|
return object : PsiElementVisitor() {
|
||||||
override fun visitElement(element: PsiElement) {
|
override fun visitElement(element: PsiElement) {
|
||||||
if (!elementType.isInstance(element) || element.getTextLength() == 0) return
|
if (!elementType.isInstance(element) || element.textLength == 0) return
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val targetElement = element as TElement
|
val targetElement = element as TElement
|
||||||
@@ -62,9 +62,9 @@ public abstract class IntentionBasedInspection<TElement : KtElement>(
|
|||||||
for ((intention, additionalChecker) in intentions) {
|
for ((intention, additionalChecker) in intentions) {
|
||||||
synchronized(intention) {
|
synchronized(intention) {
|
||||||
val range = intention.applicabilityRange(targetElement)?.let { range ->
|
val range = intention.applicabilityRange(targetElement)?.let { range ->
|
||||||
val elementRange = targetElement.getTextRange()
|
val elementRange = targetElement.textRange
|
||||||
assert(range in elementRange) { "Wrong applicabilityRange() result for $intention - should be within element's range" }
|
assert(range in elementRange) { "Wrong applicabilityRange() result for $intention - should be within element's range" }
|
||||||
range.shiftRight(-elementRange.getStartOffset())
|
range.shiftRight(-elementRange.startOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (range != null && additionalChecker(targetElement)) {
|
if (range != null && additionalChecker(targetElement)) {
|
||||||
@@ -96,13 +96,13 @@ public abstract class IntentionBasedInspection<TElement : KtElement>(
|
|||||||
) : LocalQuickFixOnPsiElement(targetElement), IntentionAction {
|
) : LocalQuickFixOnPsiElement(targetElement), IntentionAction {
|
||||||
|
|
||||||
// store text into variable because intention instance is shared and may change its text later
|
// store text into variable because intention instance is shared and may change its text later
|
||||||
override fun getFamilyName() = intention.getFamilyName()
|
override fun getFamilyName() = intention.familyName
|
||||||
|
|
||||||
override fun getText(): String = text
|
override fun getText(): String = text
|
||||||
|
|
||||||
override fun startInWriteAction() = true
|
override fun startInWriteAction() = true
|
||||||
|
|
||||||
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?) = isAvailable()
|
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?) = isAvailable
|
||||||
|
|
||||||
override fun isAvailable(project: Project, file: PsiFile, startElement: PsiElement, endElement: PsiElement): Boolean {
|
override fun isAvailable(project: Project, file: PsiFile, startElement: PsiElement, endElement: PsiElement): Boolean {
|
||||||
assert(startElement == endElement)
|
assert(startElement == endElement)
|
||||||
@@ -119,13 +119,13 @@ public abstract class IntentionBasedInspection<TElement : KtElement>(
|
|||||||
if (!isAvailable(project, file, startElement, endElement)) return
|
if (!isAvailable(project, file, startElement, endElement)) return
|
||||||
|
|
||||||
startElement.getOrCreateEditor()?.let { editor ->
|
startElement.getOrCreateEditor()?.let { editor ->
|
||||||
editor.getCaretModel().moveToOffset(startElement.getTextOffset())
|
editor.caretModel.moveToOffset(startElement.textOffset)
|
||||||
intention.applyTo(startElement as TElement, editor)
|
intention.applyTo(startElement as TElement, editor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PsiElement.getOrCreateEditor(): Editor? {
|
private fun PsiElement.getOrCreateEditor(): Editor? {
|
||||||
val file = getContainingFile()?.getVirtualFile() ?: return null
|
val file = containingFile?.virtualFile ?: return null
|
||||||
val document = FileDocumentManager.getInstance().getDocument(file) ?: return null
|
val document = FileDocumentManager.getInstance().getDocument(file) ?: return null
|
||||||
|
|
||||||
val editorFactory = EditorFactory.getInstance()
|
val editorFactory = EditorFactory.getInstance()
|
||||||
|
|||||||
+31
-31
@@ -31,11 +31,11 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
public class OperatorToFunctionIntention : SelfTargetingIntention<KtExpression>(KtExpression::class.java, "Replace overloaded operator with function call") {
|
class OperatorToFunctionIntention : SelfTargetingIntention<KtExpression>(KtExpression::class.java, "Replace overloaded operator with function call") {
|
||||||
companion object {
|
companion object {
|
||||||
private fun isApplicablePrefix(element: KtPrefixExpression, caretOffset: Int): Boolean {
|
private fun isApplicablePrefix(element: KtPrefixExpression, caretOffset: Int): Boolean {
|
||||||
val opRef = element.getOperationReference()
|
val opRef = element.operationReference
|
||||||
if (!opRef.getTextRange().containsOffset(caretOffset)) return false
|
if (!opRef.textRange.containsOffset(caretOffset)) return false
|
||||||
return when (opRef.getReferencedNameElementType()) {
|
return when (opRef.getReferencedNameElementType()) {
|
||||||
KtTokens.PLUS, KtTokens.MINUS, KtTokens.PLUSPLUS, KtTokens.MINUSMINUS, KtTokens.EXCL -> true
|
KtTokens.PLUS, KtTokens.MINUS, KtTokens.PLUSPLUS, KtTokens.MINUSMINUS, KtTokens.EXCL -> true
|
||||||
else -> false
|
else -> false
|
||||||
@@ -43,9 +43,9 @@ public class OperatorToFunctionIntention : SelfTargetingIntention<KtExpression>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun isApplicablePostfix(element: KtPostfixExpression, caretOffset: Int): Boolean {
|
private fun isApplicablePostfix(element: KtPostfixExpression, caretOffset: Int): Boolean {
|
||||||
val opRef = element.getOperationReference()
|
val opRef = element.operationReference
|
||||||
if (!opRef.getTextRange().containsOffset(caretOffset)) return false
|
if (!opRef.textRange.containsOffset(caretOffset)) return false
|
||||||
if (element.getBaseExpression() == null) return false
|
if (element.baseExpression == null) return false
|
||||||
return when (opRef.getReferencedNameElementType()) {
|
return when (opRef.getReferencedNameElementType()) {
|
||||||
KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> true
|
KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> true
|
||||||
else -> false
|
else -> false
|
||||||
@@ -53,37 +53,37 @@ public class OperatorToFunctionIntention : SelfTargetingIntention<KtExpression>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun isApplicableBinary(element: KtBinaryExpression, caretOffset: Int): Boolean {
|
private fun isApplicableBinary(element: KtBinaryExpression, caretOffset: Int): Boolean {
|
||||||
val opRef = element.getOperationReference()
|
val opRef = element.operationReference
|
||||||
if (!opRef.getTextRange().containsOffset(caretOffset)) return false
|
if (!opRef.textRange.containsOffset(caretOffset)) return false
|
||||||
return when (opRef.getReferencedNameElementType()) {
|
return when (opRef.getReferencedNameElementType()) {
|
||||||
KtTokens.PLUS, KtTokens.MINUS, KtTokens.MUL, KtTokens.DIV, KtTokens.PERC, KtTokens.RANGE, KtTokens.IN_KEYWORD, KtTokens.NOT_IN, KtTokens.PLUSEQ, KtTokens.MINUSEQ, KtTokens.MULTEQ, KtTokens.DIVEQ, KtTokens.PERCEQ, KtTokens.EQEQ, KtTokens.EXCLEQ, KtTokens.GT, KtTokens.LT, KtTokens.GTEQ, KtTokens.LTEQ -> true
|
KtTokens.PLUS, KtTokens.MINUS, KtTokens.MUL, KtTokens.DIV, KtTokens.PERC, KtTokens.RANGE, KtTokens.IN_KEYWORD, KtTokens.NOT_IN, KtTokens.PLUSEQ, KtTokens.MINUSEQ, KtTokens.MULTEQ, KtTokens.DIVEQ, KtTokens.PERCEQ, KtTokens.EQEQ, KtTokens.EXCLEQ, KtTokens.GT, KtTokens.LT, KtTokens.GTEQ, KtTokens.LTEQ -> true
|
||||||
KtTokens.EQ -> element.getLeft() is KtArrayAccessExpression
|
KtTokens.EQ -> element.left is KtArrayAccessExpression
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isApplicableArrayAccess(element: KtArrayAccessExpression, caretOffset: Int): Boolean {
|
private fun isApplicableArrayAccess(element: KtArrayAccessExpression, caretOffset: Int): Boolean {
|
||||||
val lbracket = element.getLeftBracket() ?: return false
|
val lbracket = element.leftBracket ?: return false
|
||||||
val rbracket = element.getRightBracket() ?: return false
|
val rbracket = element.rightBracket ?: return false
|
||||||
|
|
||||||
val access = element.readWriteAccess(useResolveForReadWrite = true)
|
val access = element.readWriteAccess(useResolveForReadWrite = true)
|
||||||
if (access == ReferenceAccess.READ_WRITE) return false // currently not supported
|
if (access == ReferenceAccess.READ_WRITE) return false // currently not supported
|
||||||
|
|
||||||
return lbracket.getTextRange().containsOffset(caretOffset) || rbracket.getTextRange().containsOffset(caretOffset)
|
return lbracket.textRange.containsOffset(caretOffset) || rbracket.textRange.containsOffset(caretOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isApplicableCall(element: KtCallExpression, caretOffset: Int): Boolean {
|
private fun isApplicableCall(element: KtCallExpression, caretOffset: Int): Boolean {
|
||||||
val lbrace = (element.getValueArgumentList()?.getLeftParenthesis()
|
val lbrace = (element.valueArgumentList?.leftParenthesis
|
||||||
?: element.getLambdaArguments().firstOrNull()?.getLambdaExpression()?.getLeftCurlyBrace()
|
?: element.lambdaArguments.firstOrNull()?.getLambdaExpression()?.leftCurlyBrace
|
||||||
?: return false) as PsiElement
|
?: return false) as PsiElement
|
||||||
if (!lbrace.getTextRange().containsOffset(caretOffset)) return false
|
if (!lbrace.textRange.containsOffset(caretOffset)) return false
|
||||||
|
|
||||||
val resolvedCall = element.getResolvedCall(element.analyze())
|
val resolvedCall = element.getResolvedCall(element.analyze())
|
||||||
val descriptor = resolvedCall?.getResultingDescriptor()
|
val descriptor = resolvedCall?.resultingDescriptor
|
||||||
if (descriptor is FunctionDescriptor && descriptor.getName() == OperatorNameConventions.INVOKE) {
|
if (descriptor is FunctionDescriptor && descriptor.getName() == OperatorNameConventions.INVOKE) {
|
||||||
if (element.getParent() is KtDotQualifiedExpression &&
|
if (element.parent is KtDotQualifiedExpression &&
|
||||||
element.getCalleeExpression()?.getText() == OperatorNameConventions.INVOKE.asString()) return false
|
element.calleeExpression?.text == OperatorNameConventions.INVOKE.asString()) return false
|
||||||
return element.getValueArgumentList() != null || element.getLambdaArguments().isNotEmpty()
|
return element.valueArgumentList != null || element.lambdaArguments.isNotEmpty()
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -104,7 +104,7 @@ public class OperatorToFunctionIntention : SelfTargetingIntention<KtExpression>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun convertPostFix(element: KtPostfixExpression): KtExpression {
|
private fun convertPostFix(element: KtPostfixExpression): KtExpression {
|
||||||
val op = element.getOperationReference().getReferencedNameElementType()
|
val op = element.operationReference.getReferencedNameElementType()
|
||||||
val operatorName = when (op) {
|
val operatorName = when (op) {
|
||||||
KtTokens.PLUSPLUS -> OperatorNameConventions.INC
|
KtTokens.PLUSPLUS -> OperatorNameConventions.INC
|
||||||
KtTokens.MINUSMINUS -> OperatorNameConventions.DEC
|
KtTokens.MINUSMINUS -> OperatorNameConventions.DEC
|
||||||
@@ -130,7 +130,7 @@ public class OperatorToFunctionIntention : SelfTargetingIntention<KtExpression>(
|
|||||||
|
|
||||||
val context = element.analyze(BodyResolveMode.PARTIAL)
|
val context = element.analyze(BodyResolveMode.PARTIAL)
|
||||||
val functionCandidate = element.getResolvedCall(context)
|
val functionCandidate = element.getResolvedCall(context)
|
||||||
val functionName = functionCandidate?.getCandidateDescriptor()?.getName().toString()
|
val functionName = functionCandidate?.candidateDescriptor?.name.toString()
|
||||||
val elemType = context.getType(left)
|
val elemType = context.getType(left)
|
||||||
|
|
||||||
val pattern = when (op) {
|
val pattern = when (op) {
|
||||||
@@ -194,11 +194,11 @@ public class OperatorToFunctionIntention : SelfTargetingIntention<KtExpression>(
|
|||||||
|
|
||||||
//TODO: don't use creation by plain text
|
//TODO: don't use creation by plain text
|
||||||
private fun convertCall(element: KtCallExpression): KtExpression {
|
private fun convertCall(element: KtCallExpression): KtExpression {
|
||||||
val callee = element.getCalleeExpression()!!
|
val callee = element.calleeExpression!!
|
||||||
val arguments = element.getValueArgumentList()
|
val arguments = element.valueArgumentList
|
||||||
val argumentString = arguments?.getText()?.removeSurrounding("(", ")")
|
val argumentString = arguments?.text?.removeSurrounding("(", ")")
|
||||||
val funcLitArgs = element.getLambdaArguments()
|
val funcLitArgs = element.lambdaArguments
|
||||||
val calleeText = callee.getText()
|
val calleeText = callee.text
|
||||||
val transformation = "$calleeText.${OperatorNameConventions.INVOKE.asString()}" +
|
val transformation = "$calleeText.${OperatorNameConventions.INVOKE.asString()}" +
|
||||||
(if (argumentString == null) "()" else "($argumentString)")
|
(if (argumentString == null) "()" else "($argumentString)")
|
||||||
val transformed = KtPsiFactory(element).createExpression(transformation)
|
val transformed = KtPsiFactory(element).createExpression(transformation)
|
||||||
@@ -209,10 +209,10 @@ public class OperatorToFunctionIntention : SelfTargetingIntention<KtExpression>(
|
|||||||
callExpression.valueArgumentList?.delete()
|
callExpression.valueArgumentList?.delete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return callee.getParent()!!.replace(transformed) as KtExpression
|
return callee.parent!!.replace(transformed) as KtExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun convert(element: KtExpression): Pair<KtExpression, KtSimpleNameExpression> {
|
fun convert(element: KtExpression): Pair<KtExpression, KtSimpleNameExpression> {
|
||||||
var elementToBeReplaced = element
|
var elementToBeReplaced = element
|
||||||
if (element is KtArrayAccessExpression && isAssignmentLeftSide(element)) {
|
if (element is KtArrayAccessExpression && isAssignmentLeftSide(element)) {
|
||||||
elementToBeReplaced = element.parent as KtExpression
|
elementToBeReplaced = element.parent as KtExpression
|
||||||
@@ -240,12 +240,12 @@ public class OperatorToFunctionIntention : SelfTargetingIntention<KtExpression>(
|
|||||||
return when (result) {
|
return when (result) {
|
||||||
is KtBinaryExpression -> {
|
is KtBinaryExpression -> {
|
||||||
if (KtPsiUtil.isAssignment(result))
|
if (KtPsiUtil.isAssignment(result))
|
||||||
findCallName(result.getRight()!!)
|
findCallName(result.right!!)
|
||||||
else
|
else
|
||||||
findCallName(result.getLeft()!!)
|
findCallName(result.left!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtUnaryExpression -> findCallName(result.getBaseExpression()!!)
|
is KtUnaryExpression -> findCallName(result.baseExpression!!)
|
||||||
|
|
||||||
else -> result.getQualifiedElementSelector() as KtSimpleNameExpression?
|
else -> result.getQualifiedElementSelector() as KtSimpleNameExpression?
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -34,8 +34,8 @@ import org.jetbrains.kotlin.psi.psiUtil.containsInside
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public abstract class SelfTargetingIntention<TElement : KtElement>(
|
abstract class SelfTargetingIntention<TElement : KtElement>(
|
||||||
public 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 {
|
||||||
@@ -49,12 +49,12 @@ public abstract class SelfTargetingIntention<TElement : KtElement>(
|
|||||||
final override fun getText() = text
|
final override fun getText() = text
|
||||||
final override fun getFamilyName() = familyName
|
final override fun getFamilyName() = familyName
|
||||||
|
|
||||||
public abstract fun isApplicableTo(element: TElement, caretOffset: Int): Boolean
|
abstract fun isApplicableTo(element: TElement, caretOffset: Int): Boolean
|
||||||
|
|
||||||
public abstract fun applyTo(element: TElement, editor: Editor)
|
abstract fun applyTo(element: TElement, editor: Editor)
|
||||||
|
|
||||||
private fun getTarget(editor: Editor, file: PsiFile): TElement? {
|
private fun getTarget(editor: Editor, file: PsiFile): TElement? {
|
||||||
val offset = editor.getCaretModel().getOffset()
|
val offset = editor.caretModel.offset
|
||||||
val leaf1 = file.findElementAt(offset)
|
val leaf1 = file.findElementAt(offset)
|
||||||
val leaf2 = file.findElementAt(offset - 1)
|
val leaf2 = file.findElementAt(offset - 1)
|
||||||
val commonParent = if (leaf1 != null && leaf2 != null) PsiTreeUtil.findCommonParent(leaf1, leaf2) else null
|
val commonParent = if (leaf1 != null && leaf2 != null) PsiTreeUtil.findCommonParent(leaf1, leaf2) else null
|
||||||
@@ -75,7 +75,7 @@ public abstract class SelfTargetingIntention<TElement : KtElement>(
|
|||||||
if (elementType.isInstance(element) && isApplicableTo(element as TElement, offset)) {
|
if (elementType.isInstance(element) && isApplicableTo(element as TElement, offset)) {
|
||||||
return element
|
return element
|
||||||
}
|
}
|
||||||
if (!allowCaretInsideElement(element) && element.getTextRange().containsInside(offset)) break
|
if (!allowCaretInsideElement(element) && element.textRange.containsInside(offset)) break
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -131,13 +131,13 @@ public abstract class SelfTargetingIntention<TElement : KtElement>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class SelfTargetingRangeIntention<TElement : KtElement>(
|
abstract class SelfTargetingRangeIntention<TElement : KtElement>(
|
||||||
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) {
|
||||||
|
|
||||||
public abstract fun applicabilityRange(element: TElement): TextRange?
|
abstract fun applicabilityRange(element: TElement): TextRange?
|
||||||
|
|
||||||
override final fun isApplicableTo(element: TElement, caretOffset: Int): Boolean {
|
override final fun isApplicableTo(element: TElement, caretOffset: Int): Boolean {
|
||||||
val range = applicabilityRange(element) ?: return false
|
val range = applicabilityRange(element) ?: return false
|
||||||
@@ -145,15 +145,15 @@ public abstract class SelfTargetingRangeIntention<TElement : KtElement>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public 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) {
|
||||||
|
|
||||||
public abstract fun isApplicableTo(element: TElement): Boolean
|
abstract fun isApplicableTo(element: TElement): Boolean
|
||||||
|
|
||||||
override final fun applicabilityRange(element: TElement): TextRange? {
|
override final fun applicabilityRange(element: TElement): TextRange? {
|
||||||
return if (isApplicableTo(element)) element.getTextRange() else null
|
return if (isApplicableTo(element)) element.textRange else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
||||||
|
|
||||||
class KDocElementFactory(val project: Project) {
|
class KDocElementFactory(val project: Project) {
|
||||||
public fun createKDocFromText(text: String): KDoc {
|
fun createKDocFromText(text: String): KDoc {
|
||||||
val fileText = text + " fun foo { }"
|
val fileText = text + " fun foo { }"
|
||||||
val function = KtPsiFactory(project).createDeclaration<KtFunction>(fileText)
|
val function = KtPsiFactory(project).createDeclaration<KtFunction>(fileText)
|
||||||
return PsiTreeUtil.findChildOfType(function, KDoc::class.java)!!
|
return PsiTreeUtil.findChildOfType(function, KDoc::class.java)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun createNameFromText(text: String): KDocName {
|
fun createNameFromText(text: String): KDocName {
|
||||||
val kdoc = createKDocFromText("/** @param $text foo*/")
|
val kdoc = createKDocFromText("/** @param $text foo*/")
|
||||||
val section = kdoc.getDefaultSection()
|
val section = kdoc.getDefaultSection()
|
||||||
val tag = section.findTagByName("param")
|
val tag = section.findTagByName("param")
|
||||||
|
|||||||
@@ -28,14 +28,14 @@ import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
|||||||
object KDocFinder {
|
object KDocFinder {
|
||||||
fun findKDoc(declaration: DeclarationDescriptor): KDocTag? {
|
fun findKDoc(declaration: DeclarationDescriptor): KDocTag? {
|
||||||
if (declaration is DeclarationDescriptorWithSource) {
|
if (declaration is DeclarationDescriptorWithSource) {
|
||||||
var psiDeclaration = (declaration.getSource() as? PsiSourceElement)?.psi?.getNavigationElement()
|
var psiDeclaration = (declaration.source as? PsiSourceElement)?.psi?.navigationElement
|
||||||
// KDoc for primary constructor is located inside of its class KDoc
|
// KDoc for primary constructor is located inside of its class KDoc
|
||||||
if (psiDeclaration is KtPrimaryConstructor) {
|
if (psiDeclaration is KtPrimaryConstructor) {
|
||||||
psiDeclaration = psiDeclaration.getContainingClassOrObject()
|
psiDeclaration = psiDeclaration.getContainingClassOrObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (psiDeclaration is KtDeclaration) {
|
if (psiDeclaration is KtDeclaration) {
|
||||||
val kdoc = psiDeclaration.getDocComment()
|
val kdoc = psiDeclaration.docComment
|
||||||
if (kdoc != null) {
|
if (kdoc != null) {
|
||||||
if (declaration is ConstructorDescriptor) {
|
if (declaration is ConstructorDescriptor) {
|
||||||
// ConstructorDescriptor resolves to the same JetDeclaration
|
// ConstructorDescriptor resolves to the same JetDeclaration
|
||||||
@@ -50,7 +50,7 @@ object KDocFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (declaration is PropertyDescriptor) {
|
if (declaration is PropertyDescriptor) {
|
||||||
val containingClassDescriptor = declaration.getContainingDeclaration() as? ClassDescriptor
|
val containingClassDescriptor = declaration.containingDeclaration as? ClassDescriptor
|
||||||
if (containingClassDescriptor != null) {
|
if (containingClassDescriptor != null) {
|
||||||
val classKDoc = findKDoc(containingClassDescriptor)?.getParentOfType<KDoc>(false)
|
val classKDoc = findKDoc(containingClassDescriptor)?.getParentOfType<KDoc>(false)
|
||||||
if (classKDoc != null) {
|
if (classKDoc != null) {
|
||||||
@@ -64,8 +64,8 @@ object KDocFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (declaration is CallableDescriptor) {
|
if (declaration is CallableDescriptor) {
|
||||||
for (baseDescriptor in declaration.getOverriddenDescriptors()) {
|
for (baseDescriptor in declaration.overriddenDescriptors) {
|
||||||
val baseKDoc = findKDoc(baseDescriptor.getOriginal())
|
val baseKDoc = findKDoc(baseDescriptor.original)
|
||||||
if (baseKDoc != null) {
|
if (baseKDoc != null) {
|
||||||
return baseKDoc
|
return baseKDoc
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink
|
|||||||
class KDocHighlightingVisitor(private val holder: AnnotationHolder): PsiElementVisitor() {
|
class KDocHighlightingVisitor(private val holder: AnnotationHolder): PsiElementVisitor() {
|
||||||
override fun visitElement(element: PsiElement) {
|
override fun visitElement(element: PsiElement) {
|
||||||
if (element is KDocLink) {
|
if (element is KDocLink) {
|
||||||
holder.createInfoAnnotation(element, null).setTextAttributes(KotlinHighlightingColors.KDOC_LINK)
|
holder.createInfoAnnotation(element, null).textAttributes = KotlinHighlightingColors.KDOC_LINK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.resolve.scopes.utils.collectDescriptorsFiltered
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
|
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
|
||||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||||
|
|
||||||
public class KDocReference(element: KDocName): KtMultiReference<KDocName>(element) {
|
class KDocReference(element: KDocName): KtMultiReference<KDocName>(element) {
|
||||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||||
val declaration = element.getContainingDoc().getOwner() ?: return arrayListOf()
|
val declaration = element.getContainingDoc().getOwner() ?: return arrayListOf()
|
||||||
val declarationDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] ?: return arrayListOf()
|
val declarationDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] ?: return arrayListOf()
|
||||||
@@ -64,7 +64,7 @@ public class KDocReference(element: KDocName): KtMultiReference<KDocName>(elemen
|
|||||||
override fun getCanonicalText(): String = element.getNameText()
|
override fun getCanonicalText(): String = element.getNameText()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun resolveKDocLink(resolutionFacade: ResolutionFacade,
|
fun resolveKDocLink(resolutionFacade: ResolutionFacade,
|
||||||
fromDescriptor: DeclarationDescriptor,
|
fromDescriptor: DeclarationDescriptor,
|
||||||
fromSubjectOfTag: KDocTag?,
|
fromSubjectOfTag: KDocTag?,
|
||||||
qualifiedName: List<String>): Collection<DeclarationDescriptor> {
|
qualifiedName: List<String>): Collection<DeclarationDescriptor> {
|
||||||
@@ -98,7 +98,7 @@ private fun resolveInLocalScope(fromDescriptor: DeclarationDescriptor,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getParamDescriptors(fromDescriptor: DeclarationDescriptor): List<DeclarationDescriptor> {
|
fun getParamDescriptors(fromDescriptor: DeclarationDescriptor): List<DeclarationDescriptor> {
|
||||||
// TODO resolve parameters of functions passed as parameters
|
// TODO resolve parameters of functions passed as parameters
|
||||||
when (fromDescriptor) {
|
when (fromDescriptor) {
|
||||||
is CallableDescriptor ->
|
is CallableDescriptor ->
|
||||||
@@ -151,7 +151,7 @@ private fun getClassInnerScope(outerScope: LexicalScope, descriptor: ClassDescri
|
|||||||
scopeChain)
|
scopeChain)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getResolutionScope(resolutionFacade: ResolutionFacade, descriptor: DeclarationDescriptor): LexicalScope {
|
fun getResolutionScope(resolutionFacade: ResolutionFacade, descriptor: DeclarationDescriptor): LexicalScope {
|
||||||
return when (descriptor) {
|
return when (descriptor) {
|
||||||
is PackageFragmentDescriptor ->
|
is PackageFragmentDescriptor ->
|
||||||
LexicalScope.empty(getPackageInnerScope(descriptor).memberScopeAsImportingScope(), descriptor)
|
LexicalScope.empty(getPackageInnerScope(descriptor).memberScopeAsImportingScope(), descriptor)
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ import com.intellij.psi.PsiElement
|
|||||||
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
|
||||||
|
|
||||||
public 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)
|
||||||
|
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
|
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
|
||||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||||
|
|
||||||
public object AnalyzerFacadeProvider {
|
object AnalyzerFacadeProvider {
|
||||||
//NOTE: it's convenient that JS backend doesn't have platform parameters (for now)
|
//NOTE: it's convenient that JS backend doesn't have platform parameters (for now)
|
||||||
// otherwise we would be forced to add casts on the call site of setupResolverForProject
|
// otherwise we would be forced to add casts on the call site of setupResolverForProject
|
||||||
public fun getAnalyzerFacade(targetPlatform: TargetPlatform): AnalyzerFacade<JvmPlatformParameters> {
|
fun getAnalyzerFacade(targetPlatform: TargetPlatform): AnalyzerFacade<JvmPlatformParameters> {
|
||||||
return when (targetPlatform) {
|
return when (targetPlatform) {
|
||||||
JvmPlatform -> JvmAnalyzerFacade
|
JvmPlatform -> JvmAnalyzerFacade
|
||||||
JsPlatform -> JsAnalyzerFacade
|
JsPlatform -> JsAnalyzerFacade
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.container.StorageComponentContainer
|
|||||||
import org.jetbrains.kotlin.container.useImpl
|
import org.jetbrains.kotlin.container.useImpl
|
||||||
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
||||||
|
|
||||||
public object IdeaEnvironment : TargetEnvironment("Idea") {
|
object IdeaEnvironment : TargetEnvironment("Idea") {
|
||||||
override fun configure(container: StorageComponentContainer) {
|
override fun configure(container: StorageComponentContainer) {
|
||||||
container.useImpl<ResolveElementCache>()
|
container.useImpl<ResolveElementCache>()
|
||||||
container.useImpl<IdeaLocalDescriptorResolver>()
|
container.useImpl<IdeaLocalDescriptorResolver>()
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ 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.NoDescriptorForDeclarationException
|
import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException
|
||||||
|
|
||||||
public class IdeaLocalDescriptorResolver(
|
class IdeaLocalDescriptorResolver(
|
||||||
private val resolveElementCache: ResolveElementCache
|
private val resolveElementCache: ResolveElementCache
|
||||||
): LocalDescriptorResolver {
|
): LocalDescriptorResolver {
|
||||||
override fun resolveLocalDeclaration(declaration: KtDeclaration): DeclarationDescriptor {
|
override fun resolveLocalDeclaration(declaration: KtDeclaration): DeclarationDescriptor {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
|
|
||||||
public class ResolveElementCache(
|
class ResolveElementCache(
|
||||||
private val resolveSession: ResolveSession,
|
private val resolveSession: ResolveSession,
|
||||||
private val project: Project,
|
private val project: Project,
|
||||||
private val targetPlatform: TargetPlatform,
|
private val targetPlatform: TargetPlatform,
|
||||||
@@ -114,7 +114,7 @@ public class ResolveElementCache(
|
|||||||
override fun resolveFunctionBody(function: KtNamedFunction)
|
override fun resolveFunctionBody(function: KtNamedFunction)
|
||||||
= getElementAdditionalResolve(function, function, BodyResolveMode.FULL)
|
= getElementAdditionalResolve(function, function, BodyResolveMode.FULL)
|
||||||
|
|
||||||
public fun resolvePrimaryConstructorParametersDefaultValues(ktClass: KtClass): BindingContext {
|
fun resolvePrimaryConstructorParametersDefaultValues(ktClass: KtClass): BindingContext {
|
||||||
return constructorAdditionalResolve(resolveSession, ktClass, ktClass.getContainingKtFile()).bindingContext
|
return constructorAdditionalResolve(resolveSession, ktClass, ktClass.getContainingKtFile()).bindingContext
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ public class ResolveElementCache(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun resolveToElement(element: KtElement, bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext {
|
fun resolveToElement(element: KtElement, bodyResolveMode: BodyResolveMode = BodyResolveMode.FULL): BindingContext {
|
||||||
var contextElement = element
|
var contextElement = element
|
||||||
|
|
||||||
val elementOfAdditionalResolve = findElementOfAdditionalResolve(contextElement)
|
val elementOfAdditionalResolve = findElementOfAdditionalResolve(contextElement)
|
||||||
@@ -198,7 +198,7 @@ public class ResolveElementCache(
|
|||||||
resolveSession.resolveToDescriptor(declaration)
|
resolveSession.resolveToDescriptor(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolveSession.getBindingContext()
|
return resolveSession.bindingContext
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findElementOfAdditionalResolve(element: KtElement): KtElement? {
|
private fun findElementOfAdditionalResolve(element: KtElement): KtElement? {
|
||||||
@@ -313,11 +313,11 @@ public class ResolveElementCache(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val controlFlowTrace = DelegatingBindingTrace(trace.getBindingContext(), "Element control flow resolve", resolveElement)
|
val controlFlowTrace = DelegatingBindingTrace(trace.bindingContext, "Element control flow resolve", resolveElement)
|
||||||
ControlFlowInformationProvider(resolveElement, controlFlowTrace).checkDeclaration()
|
ControlFlowInformationProvider(resolveElement, controlFlowTrace).checkDeclaration()
|
||||||
controlFlowTrace.addOwnDataTo(trace, null, false)
|
controlFlowTrace.addOwnDataTo(trace, null, false)
|
||||||
|
|
||||||
return Pair(trace.getBindingContext(), statementFilterUsed)
|
return Pair(trace.bindingContext, statementFilterUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun packageRefAdditionalResolve(resolveSession: ResolveSession, ktElement: KtElement): BindingTrace {
|
private fun packageRefAdditionalResolve(resolveSession: ResolveSession, ktElement: KtElement): BindingTrace {
|
||||||
@@ -327,7 +327,7 @@ public class ResolveElementCache(
|
|||||||
val header = ktElement.getParentOfType<KtPackageDirective>(true)!!
|
val header = ktElement.getParentOfType<KtPackageDirective>(true)!!
|
||||||
|
|
||||||
if (Name.isValidIdentifier(ktElement.getReferencedName())) {
|
if (Name.isValidIdentifier(ktElement.getReferencedName())) {
|
||||||
if (trace.getBindingContext()[BindingContext.REFERENCE_TARGET, ktElement] == null) {
|
if (trace.bindingContext[BindingContext.REFERENCE_TARGET, ktElement] == null) {
|
||||||
val fqName = header.getFqName(ktElement)
|
val fqName = header.getFqName(ktElement)
|
||||||
val packageDescriptor = resolveSession.moduleDescriptor.getPackage(fqName)
|
val packageDescriptor = resolveSession.moduleDescriptor.getPackage(fqName)
|
||||||
trace.record(BindingContext.REFERENCE_TARGET, ktElement, packageDescriptor)
|
trace.record(BindingContext.REFERENCE_TARGET, ktElement, packageDescriptor)
|
||||||
@@ -372,7 +372,7 @@ public class ResolveElementCache(
|
|||||||
if (fileAnnotationList != null) {
|
if (fileAnnotationList != null) {
|
||||||
doResolveAnnotations(resolveSession.getFileAnnotations(fileAnnotationList.getContainingKtFile()))
|
doResolveAnnotations(resolveSession.getFileAnnotations(fileAnnotationList.getContainingKtFile()))
|
||||||
}
|
}
|
||||||
if (modifierList != null && modifierList.getParent() is KtFile) {
|
if (modifierList != null && modifierList.parent is KtFile) {
|
||||||
doResolveAnnotations(resolveSession.getDanglingAnnotations(modifierList.getContainingKtFile()))
|
doResolveAnnotations(resolveSession.getDanglingAnnotations(modifierList.getContainingKtFile()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -388,16 +388,16 @@ public class ResolveElementCache(
|
|||||||
var descriptor = resolveSession.resolveToDescriptor(declaration)
|
var descriptor = resolveSession.resolveToDescriptor(declaration)
|
||||||
if (declaration is KtClass) {
|
if (declaration is KtClass) {
|
||||||
if (modifierList == declaration.getPrimaryConstructorModifierList()) {
|
if (modifierList == declaration.getPrimaryConstructorModifierList()) {
|
||||||
descriptor = (descriptor as ClassDescriptor).getUnsubstitutedPrimaryConstructor()
|
descriptor = (descriptor as ClassDescriptor).unsubstitutedPrimaryConstructor
|
||||||
?: error("No constructor found: ${declaration.getText()}")
|
?: error("No constructor found: ${declaration.getText()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declaration is KtClassOrObject && modifierList.getParent() == declaration.getBody() && descriptor is LazyClassDescriptor) {
|
if (declaration is KtClassOrObject && modifierList.parent == declaration.getBody() && descriptor is LazyClassDescriptor) {
|
||||||
return descriptor.getDanglingAnnotations()
|
return descriptor.danglingAnnotations
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptor.getAnnotations()
|
return descriptor.annotations
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun typeParameterAdditionalResolve(analyzer: KotlinCodeAnalyzer, typeParameter: KtTypeParameter): BindingTrace {
|
private fun typeParameterAdditionalResolve(analyzer: KotlinCodeAnalyzer, typeParameter: KtTypeParameter): BindingTrace {
|
||||||
@@ -412,15 +412,15 @@ public class ResolveElementCache(
|
|||||||
val descriptor = resolveSession.resolveToDescriptor(classOrObject) as LazyClassDescriptor
|
val descriptor = resolveSession.resolveToDescriptor(classOrObject) as LazyClassDescriptor
|
||||||
|
|
||||||
// Activate resolving of supertypes
|
// Activate resolving of supertypes
|
||||||
ForceResolveUtil.forceResolveAllContents(descriptor.getTypeConstructor().getSupertypes())
|
ForceResolveUtil.forceResolveAllContents(descriptor.typeConstructor.supertypes)
|
||||||
|
|
||||||
val bodyResolver = createBodyResolver(resolveSession, trace, file, StatementFilter.NONE)
|
val bodyResolver = createBodyResolver(resolveSession, trace, file, StatementFilter.NONE)
|
||||||
bodyResolver.resolveSuperTypeEntryList(DataFlowInfo.EMPTY,
|
bodyResolver.resolveSuperTypeEntryList(DataFlowInfo.EMPTY,
|
||||||
classOrObject,
|
classOrObject,
|
||||||
descriptor,
|
descriptor,
|
||||||
descriptor.getUnsubstitutedPrimaryConstructor(),
|
descriptor.unsubstitutedPrimaryConstructor,
|
||||||
descriptor.scopeForConstructorHeaderResolution,
|
descriptor.scopeForConstructorHeaderResolution,
|
||||||
descriptor.getScopeForMemberDeclarationResolution())
|
descriptor.scopeForMemberDeclarationResolution)
|
||||||
|
|
||||||
return trace
|
return trace
|
||||||
}
|
}
|
||||||
@@ -433,7 +433,7 @@ public class ResolveElementCache(
|
|||||||
ForceResolveUtil.forceResolveAllContents(descriptor)
|
ForceResolveUtil.forceResolveAllContents(descriptor)
|
||||||
|
|
||||||
val bodyResolveContext = BodyResolveContextForLazy(TopDownAnalysisMode.LocalDeclarations, { declaration ->
|
val bodyResolveContext = BodyResolveContextForLazy(TopDownAnalysisMode.LocalDeclarations, { declaration ->
|
||||||
assert(declaration.getParent() == property || declaration == property) {
|
assert(declaration.parent == property || declaration == property) {
|
||||||
"Must be called only for property accessors or for property, but called for $declaration"
|
"Must be called only for property accessors or for property, but called for $declaration"
|
||||||
}
|
}
|
||||||
resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(declaration)
|
resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(declaration)
|
||||||
@@ -443,7 +443,7 @@ public class ResolveElementCache(
|
|||||||
|
|
||||||
forceResolveAnnotationsInside(property)
|
forceResolveAnnotationsInside(property)
|
||||||
|
|
||||||
for (accessor in property.getAccessors()) {
|
for (accessor in property.accessors) {
|
||||||
ControlFlowInformationProvider(accessor, trace).checkDeclaration()
|
ControlFlowInformationProvider(accessor, trace).checkDeclaration()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,7 +485,7 @@ public class ResolveElementCache(
|
|||||||
val scope = resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(klass)
|
val scope = resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(klass)
|
||||||
|
|
||||||
val classDescriptor = resolveSession.resolveToDescriptor(klass) as ClassDescriptor
|
val classDescriptor = resolveSession.resolveToDescriptor(klass) as ClassDescriptor
|
||||||
val constructorDescriptor = classDescriptor.getUnsubstitutedPrimaryConstructor()
|
val constructorDescriptor = classDescriptor.unsubstitutedPrimaryConstructor
|
||||||
?: error("Can't get primary constructor for descriptor '$classDescriptor' in from class '${klass.getElementTextWithContext()}'")
|
?: error("Can't get primary constructor for descriptor '$classDescriptor' in from class '${klass.getElementTextWithContext()}'")
|
||||||
|
|
||||||
val bodyResolver = createBodyResolver(resolveSession, trace, file, StatementFilter.NONE)
|
val bodyResolver = createBodyResolver(resolveSession, trace, file, StatementFilter.NONE)
|
||||||
@@ -521,10 +521,10 @@ public class ResolveElementCache(
|
|||||||
file: KtFile,
|
file: KtFile,
|
||||||
statementFilter: StatementFilter
|
statementFilter: StatementFilter
|
||||||
): BodyResolver {
|
): BodyResolver {
|
||||||
val globalContext = SimpleGlobalContext(resolveSession.storageManager, resolveSession.getExceptionTracker())
|
val globalContext = SimpleGlobalContext(resolveSession.storageManager, resolveSession.exceptionTracker)
|
||||||
val module = resolveSession.moduleDescriptor
|
val module = resolveSession.moduleDescriptor
|
||||||
return createContainerForBodyResolve(
|
return createContainerForBodyResolve(
|
||||||
globalContext.withProject(file.getProject()).withModule(module),
|
globalContext.withProject(file.project).withModule(module),
|
||||||
trace,
|
trace,
|
||||||
targetPlatform,
|
targetPlatform,
|
||||||
statementFilter
|
statementFilter
|
||||||
@@ -534,7 +534,7 @@ public class ResolveElementCache(
|
|||||||
// All additional resolve should be done to separate trace
|
// All additional resolve should be done to separate trace
|
||||||
private fun createDelegatingTrace(resolveElement: KtElement): BindingTrace {
|
private fun createDelegatingTrace(resolveElement: KtElement): BindingTrace {
|
||||||
return resolveSession.storageManager.createSafeTrace(
|
return resolveSession.storageManager.createSafeTrace(
|
||||||
DelegatingBindingTrace(resolveSession.getBindingContext(), "trace to resolve element", resolveElement))
|
DelegatingBindingTrace(resolveSession.bindingContext, "trace to resolve element", resolveElement))
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BodyResolveContextForLazy(
|
private class BodyResolveContextForLazy(
|
||||||
|
|||||||
+4
-4
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic
|
|||||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||||
|
|
||||||
public abstract class KotlinIntentionActionsFactory {
|
abstract class KotlinIntentionActionsFactory {
|
||||||
protected open fun isApplicableForCodeFragment(): Boolean = false
|
protected open fun isApplicableForCodeFragment(): Boolean = false
|
||||||
|
|
||||||
protected abstract fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction>
|
protected abstract fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction>
|
||||||
@@ -29,17 +29,17 @@ public abstract class KotlinIntentionActionsFactory {
|
|||||||
protected open fun doCreateActionsForAllProblems(
|
protected open fun doCreateActionsForAllProblems(
|
||||||
sameTypeDiagnostics: Collection<Diagnostic>): List<IntentionAction> = emptyList()
|
sameTypeDiagnostics: Collection<Diagnostic>): List<IntentionAction> = emptyList()
|
||||||
|
|
||||||
public fun createActions(diagnostic: Diagnostic): List<IntentionAction> =
|
fun createActions(diagnostic: Diagnostic): List<IntentionAction> =
|
||||||
createActions(diagnostic.singletonOrEmptyList(), false)
|
createActions(diagnostic.singletonOrEmptyList(), false)
|
||||||
|
|
||||||
public 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()
|
||||||
val first = sameTypeDiagnostics.first()
|
val first = sameTypeDiagnostics.first()
|
||||||
|
|
||||||
if (first.psiElement.getContainingFile() is KtCodeFragment && !isApplicableForCodeFragment()) {
|
if (first.psiElement.containingFile is KtCodeFragment && !isApplicableForCodeFragment()) {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-13
@@ -44,7 +44,7 @@ class KotlinSuppressIntentionAction private constructor(
|
|||||||
override fun getFamilyName() = KotlinBundle.message("suppress.warnings.family")
|
override fun getFamilyName() = KotlinBundle.message("suppress.warnings.family")
|
||||||
override fun getText() = KotlinBundle.message("suppress.warning.for", suppressKey, kind.kind, kind.name)
|
override fun getText() = KotlinBundle.message("suppress.warning.for", suppressKey, kind.kind, kind.name)
|
||||||
|
|
||||||
override fun isAvailable(project: Project, editor: Editor?, element: PsiElement) = element.isValid()
|
override fun isAvailable(project: Project, editor: Editor?, element: PsiElement) = element.isValid
|
||||||
|
|
||||||
override fun invoke(project: Project, editor: Editor?, element: PsiElement) {
|
override fun invoke(project: Project, editor: Editor?, element: PsiElement) {
|
||||||
val id = "\"$suppressKey\""
|
val id = "\"$suppressKey\""
|
||||||
@@ -88,7 +88,7 @@ class KotlinSuppressIntentionAction private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun suppressAtModifierListOwner(suppressAt: KtModifierListOwner, id: String) {
|
private fun suppressAtModifierListOwner(suppressAt: KtModifierListOwner, id: String) {
|
||||||
val modifierList = suppressAt.getModifierList()
|
val modifierList = suppressAt.modifierList
|
||||||
val psiFactory = KtPsiFactory(suppressAt)
|
val psiFactory = KtPsiFactory(suppressAt)
|
||||||
if (modifierList == null) {
|
if (modifierList == null) {
|
||||||
// create a modifier list from scratch
|
// create a modifier list from scratch
|
||||||
@@ -102,7 +102,7 @@ class KotlinSuppressIntentionAction private constructor(
|
|||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
// no [suppress] annotation
|
// no [suppress] annotation
|
||||||
val newAnnotation = psiFactory.createAnnotationEntry(suppressAnnotationText(id))
|
val newAnnotation = psiFactory.createAnnotationEntry(suppressAnnotationText(id))
|
||||||
val addedAnnotation = modifierList.addBefore(newAnnotation, modifierList.getFirstChild())
|
val addedAnnotation = modifierList.addBefore(newAnnotation, modifierList.firstChild)
|
||||||
val whiteSpace = psiFactory.createWhiteSpace(kind)
|
val whiteSpace = psiFactory.createWhiteSpace(kind)
|
||||||
modifierList.addAfter(whiteSpace, addedAnnotation)
|
modifierList.addAfter(whiteSpace, addedAnnotation)
|
||||||
}
|
}
|
||||||
@@ -136,8 +136,8 @@ class KotlinSuppressIntentionAction private constructor(
|
|||||||
val copy = suppressAt.copy()!!
|
val copy = suppressAt.copy()!!
|
||||||
|
|
||||||
val afterReplace = suppressAt.replace(annotatedExpression) as KtAnnotatedExpression
|
val afterReplace = suppressAt.replace(annotatedExpression) as KtAnnotatedExpression
|
||||||
val toReplace = afterReplace.findElementAt(afterReplace.getTextLength() - 2)!!
|
val toReplace = afterReplace.findElementAt(afterReplace.textLength - 2)!!
|
||||||
assert (toReplace.getText() == placeholderText)
|
assert (toReplace.text == placeholderText)
|
||||||
val result = toReplace.replace(copy)!!
|
val result = toReplace.replace(copy)!!
|
||||||
|
|
||||||
caretBox.positionCaretInCopy(result)
|
caretBox.positionCaretInCopy(result)
|
||||||
@@ -145,19 +145,19 @@ class KotlinSuppressIntentionAction private constructor(
|
|||||||
|
|
||||||
private fun addArgumentToSuppressAnnotation(entry: KtAnnotationEntry, id: String) {
|
private fun addArgumentToSuppressAnnotation(entry: KtAnnotationEntry, id: String) {
|
||||||
// add new arguments to an existing entry
|
// add new arguments to an existing entry
|
||||||
val args = entry.getValueArgumentList()
|
val args = entry.valueArgumentList
|
||||||
val psiFactory = KtPsiFactory(entry)
|
val psiFactory = KtPsiFactory(entry)
|
||||||
val newArgList = psiFactory.createCallArguments("($id)")
|
val newArgList = psiFactory.createCallArguments("($id)")
|
||||||
if (args == null) {
|
if (args == null) {
|
||||||
// new argument list
|
// new argument list
|
||||||
entry.addAfter(newArgList, entry.getLastChild())
|
entry.addAfter(newArgList, entry.lastChild)
|
||||||
}
|
}
|
||||||
else if (args.getArguments().isEmpty()) {
|
else if (args.arguments.isEmpty()) {
|
||||||
// replace '()' with a new argument list
|
// replace '()' with a new argument list
|
||||||
args.replace(newArgList)
|
args.replace(newArgList)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
args.addArgument(newArgList.getArguments()[0])
|
args.addArgument(newArgList.arguments[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ class KotlinSuppressIntentionAction private constructor(
|
|||||||
|
|
||||||
private fun findSuppressAnnotation(annotated: KtAnnotated): KtAnnotationEntry? {
|
private fun findSuppressAnnotation(annotated: KtAnnotated): KtAnnotationEntry? {
|
||||||
val context = annotated.analyze()
|
val context = annotated.analyze()
|
||||||
return findSuppressAnnotation(context, annotated.getAnnotationEntries())
|
return findSuppressAnnotation(context, annotated.annotationEntries)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findSuppressAnnotation(annotationList: KtFileAnnotationList): KtAnnotationEntry? {
|
private fun findSuppressAnnotation(annotationList: KtFileAnnotationList): KtAnnotationEntry? {
|
||||||
@@ -184,7 +184,7 @@ class KotlinSuppressIntentionAction private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AnnotationHostKind(val kind: String, val name: String, val newLineNeeded: Boolean)
|
class AnnotationHostKind(val kind: String, val name: String, val newLineNeeded: Boolean)
|
||||||
|
|
||||||
private fun KtPsiFactory.createWhiteSpace(kind: AnnotationHostKind): PsiElement {
|
private fun KtPsiFactory.createWhiteSpace(kind: AnnotationHostKind): PsiElement {
|
||||||
return if (kind.newLineNeeded) createNewLine() else createWhiteSpace()
|
return if (kind.newLineNeeded) createNewLine() else createWhiteSpace()
|
||||||
@@ -194,10 +194,10 @@ private class CaretBox<out E: KtExpression>(
|
|||||||
val expression: E,
|
val expression: E,
|
||||||
private val editor: Editor?
|
private val editor: Editor?
|
||||||
) {
|
) {
|
||||||
private val offsetInExpression: Int = (editor?.getCaretModel()?.getOffset() ?: 0) - expression.getTextRange()!!.getStartOffset()
|
private val offsetInExpression: Int = (editor?.caretModel?.offset ?: 0) - expression.textRange!!.startOffset
|
||||||
|
|
||||||
fun positionCaretInCopy(copy: PsiElement) {
|
fun positionCaretInCopy(copy: PsiElement) {
|
||||||
if (editor == null) return
|
if (editor == null) return
|
||||||
editor.getCaretModel().moveToOffset(copy.getTextOffset() + offsetInExpression)
|
editor.caretModel.moveToOffset(copy.textOffset + offsetInExpression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import com.intellij.openapi.extensions.ExtensionPointName
|
|||||||
import com.intellij.openapi.extensions.Extensions
|
import com.intellij.openapi.extensions.Extensions
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||||
|
|
||||||
public 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>()
|
||||||
|
|
||||||
@@ -32,32 +32,32 @@ public class QuickFixes {
|
|||||||
Extensions.getExtensions(QuickFixContributor.EP_NAME).forEach { it.registerQuickFixes(this) }
|
Extensions.getExtensions(QuickFixContributor.EP_NAME).forEach { it.registerQuickFixes(this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun register(diagnosticFactory: DiagnosticFactory<*>, vararg factory: KotlinIntentionActionsFactory) {
|
fun register(diagnosticFactory: DiagnosticFactory<*>, vararg factory: KotlinIntentionActionsFactory) {
|
||||||
factories.putAll(diagnosticFactory, factory.toList())
|
factories.putAll(diagnosticFactory, factory.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun register(diagnosticFactory: DiagnosticFactory<*>, vararg action: IntentionAction) {
|
fun register(diagnosticFactory: DiagnosticFactory<*>, vararg action: IntentionAction) {
|
||||||
actions.putAll(diagnosticFactory, action.toList())
|
actions.putAll(diagnosticFactory, action.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getActionFactories(diagnosticFactory: DiagnosticFactory<*>): Collection<KotlinIntentionActionsFactory> {
|
fun getActionFactories(diagnosticFactory: DiagnosticFactory<*>): Collection<KotlinIntentionActionsFactory> {
|
||||||
return factories.get(diagnosticFactory)
|
return factories.get(diagnosticFactory)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getActions(diagnosticFactory: DiagnosticFactory<*>): Collection<IntentionAction> {
|
fun getActions(diagnosticFactory: DiagnosticFactory<*>): Collection<IntentionAction> {
|
||||||
return actions.get(diagnosticFactory)
|
return actions.get(diagnosticFactory)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getDiagnostics(factory: KotlinIntentionActionsFactory): Collection<DiagnosticFactory<*>> {
|
fun getDiagnostics(factory: KotlinIntentionActionsFactory): Collection<DiagnosticFactory<*>> {
|
||||||
return factories.keySet().filter { factory in factories.get(it) }
|
return factories.keySet().filter { factory in factories.get(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
public fun getInstance(): QuickFixes = ServiceManager.getService(QuickFixes::class.java)
|
fun getInstance(): QuickFixes = ServiceManager.getService(QuickFixes::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface QuickFixContributor {
|
interface QuickFixContributor {
|
||||||
companion object {
|
companion object {
|
||||||
val EP_NAME: ExtensionPointName<QuickFixContributor> = ExtensionPointName.create("org.jetbrains.kotlin.quickFixContributor")
|
val EP_NAME: ExtensionPointName<QuickFixContributor> = ExtensionPointName.create("org.jetbrains.kotlin.quickFixContributor")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.utils.ifEmpty
|
import org.jetbrains.kotlin.utils.ifEmpty
|
||||||
|
|
||||||
public fun moveCaretIntoGeneratedElement(editor: Editor, element: PsiElement) {
|
fun moveCaretIntoGeneratedElement(editor: Editor, element: PsiElement) {
|
||||||
val project = element.project
|
val project = element.project
|
||||||
val pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(element)
|
val pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(element)
|
||||||
|
|
||||||
@@ -47,22 +47,22 @@ private fun moveCaretIntoGeneratedElementDocumentUnblocked(editor: Editor, eleme
|
|||||||
// Inspired by GenerateMembersUtils.positionCaret()
|
// Inspired by GenerateMembersUtils.positionCaret()
|
||||||
|
|
||||||
if (element is KtDeclarationWithBody && element.hasBody()) {
|
if (element is KtDeclarationWithBody && element.hasBody()) {
|
||||||
val expression = element.getBodyExpression()
|
val expression = element.bodyExpression
|
||||||
if (expression is KtBlockExpression) {
|
if (expression is KtBlockExpression) {
|
||||||
val lBrace = expression.getLBrace()
|
val lBrace = expression.lBrace
|
||||||
val rBrace = expression.getRBrace()
|
val rBrace = expression.rBrace
|
||||||
|
|
||||||
if (lBrace != null && rBrace != null) {
|
if (lBrace != null && rBrace != null) {
|
||||||
val firstInBlock = lBrace.siblings(forward = true, withItself = false).first { it !is PsiWhiteSpace }
|
val firstInBlock = lBrace.siblings(forward = true, withItself = false).first { it !is PsiWhiteSpace }
|
||||||
val lastInBlock = rBrace.siblings(forward = false, withItself = false).first { it !is PsiWhiteSpace }
|
val lastInBlock = rBrace.siblings(forward = false, withItself = false).first { it !is PsiWhiteSpace }
|
||||||
|
|
||||||
val start = firstInBlock.getTextRange()!!.getStartOffset()
|
val start = firstInBlock.textRange!!.startOffset
|
||||||
val end = lastInBlock.getTextRange()!!.getEndOffset()
|
val end = lastInBlock.textRange!!.endOffset
|
||||||
|
|
||||||
editor.moveCaret(Math.min(start, end))
|
editor.moveCaret(Math.min(start, end))
|
||||||
|
|
||||||
if (start < end) {
|
if (start < end) {
|
||||||
editor.getSelectionModel().setSelection(start, end)
|
editor.selectionModel.setSelection(start, end)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@@ -71,24 +71,24 @@ private fun moveCaretIntoGeneratedElementDocumentUnblocked(editor: Editor, eleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (element is KtWithExpressionInitializer && element.hasInitializer()) {
|
if (element is KtWithExpressionInitializer && element.hasInitializer()) {
|
||||||
val expression = element.getInitializer()
|
val expression = element.initializer
|
||||||
if (expression == null) throw AssertionError()
|
if (expression == null) throw AssertionError()
|
||||||
|
|
||||||
val initializerRange = expression.getTextRange()
|
val initializerRange = expression.textRange
|
||||||
|
|
||||||
val offset = initializerRange?.getStartOffset() ?: element.getTextOffset()
|
val offset = initializerRange?.startOffset ?: element.getTextOffset()
|
||||||
|
|
||||||
editor.moveCaret(offset)
|
editor.moveCaret(offset)
|
||||||
|
|
||||||
if (initializerRange != null) {
|
if (initializerRange != null) {
|
||||||
editor.getSelectionModel().setSelection(initializerRange.getStartOffset(), initializerRange.getEndOffset())
|
editor.selectionModel.setSelection(initializerRange.startOffset, initializerRange.endOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element is KtProperty) {
|
if (element is KtProperty) {
|
||||||
for (accessor in element.getAccessors()) {
|
for (accessor in element.accessors) {
|
||||||
if (moveCaretIntoGeneratedElementDocumentUnblocked(editor, accessor)) {
|
if (moveCaretIntoGeneratedElementDocumentUnblocked(editor, accessor)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -98,9 +98,9 @@ private fun moveCaretIntoGeneratedElementDocumentUnblocked(editor: Editor, eleme
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Editor.moveCaret(offset: Int, scrollType: ScrollType = ScrollType.RELATIVE) {
|
fun Editor.moveCaret(offset: Int, scrollType: ScrollType = ScrollType.RELATIVE) {
|
||||||
getCaretModel().moveToOffset(offset)
|
caretModel.moveToOffset(offset)
|
||||||
getScrollingModel().scrollToCaret(scrollType)
|
scrollingModel.scrollToCaret(scrollType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findInsertAfterAnchor(editor: Editor?, body: KtClassBody): PsiElement? {
|
private fun findInsertAfterAnchor(editor: Editor?, body: KtClassBody): PsiElement? {
|
||||||
@@ -145,7 +145,7 @@ private fun removeAfterOffset(offset: Int, whiteSpace: PsiWhiteSpace): PsiElemen
|
|||||||
return whiteSpace
|
return whiteSpace
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <T : KtDeclaration> insertMembersAfter(
|
fun <T : KtDeclaration> insertMembersAfter(
|
||||||
editor: Editor?,
|
editor: Editor?,
|
||||||
classOrObject: KtClassOrObject,
|
classOrObject: KtClassOrObject,
|
||||||
members: Collection<T>,
|
members: Collection<T>,
|
||||||
@@ -201,6 +201,6 @@ public fun <T : KtDeclaration> insertMembersAfter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <T : KtDeclaration> insertMember(editor: Editor, classOrObject: KtClassOrObject, declaration: T): T {
|
fun <T : KtDeclaration> insertMember(editor: Editor, classOrObject: KtClassOrObject, declaration: T): T {
|
||||||
return insertMembersAfter(editor, classOrObject, listOf(declaration)).single()
|
return insertMembersAfter(editor, classOrObject, listOf(declaration)).single()
|
||||||
}
|
}
|
||||||
@@ -28,30 +28,30 @@ import org.jetbrains.kotlin.resolve.ImportPath
|
|||||||
/**
|
/**
|
||||||
* Returns FqName for given declaration (either Java or Kotlin)
|
* Returns FqName for given declaration (either Java or Kotlin)
|
||||||
*/
|
*/
|
||||||
public fun PsiElement.getKotlinFqName(): FqName? {
|
fun PsiElement.getKotlinFqName(): FqName? {
|
||||||
val element = namedUnwrappedElement
|
val element = namedUnwrappedElement
|
||||||
return when (element) {
|
return when (element) {
|
||||||
is PsiPackage -> FqName(element.getQualifiedName())
|
is PsiPackage -> FqName(element.qualifiedName)
|
||||||
is PsiClass -> element.getQualifiedName()?.let { FqName(it) }
|
is PsiClass -> element.qualifiedName?.let { FqName(it) }
|
||||||
is PsiMember -> element.getName()?.let { name ->
|
is PsiMember -> element.getName()?.let { name ->
|
||||||
val prefix = element.getContainingClass()?.getQualifiedName()
|
val prefix = element.containingClass?.qualifiedName
|
||||||
FqName(if (prefix != null) "$prefix.$name" else name)
|
FqName(if (prefix != null) "$prefix.$name" else name)
|
||||||
}
|
}
|
||||||
is KtNamedDeclaration -> element.getFqName()
|
is KtNamedDeclaration -> element.fqName
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun FqName.isImported(importPath: ImportPath, skipAliasedImports: Boolean = true): Boolean {
|
fun FqName.isImported(importPath: ImportPath, skipAliasedImports: Boolean = true): Boolean {
|
||||||
return when {
|
return when {
|
||||||
skipAliasedImports && importPath.hasAlias() -> false
|
skipAliasedImports && importPath.hasAlias() -> false
|
||||||
importPath.isAllUnder() && !isRoot() -> importPath.fqnPart() == this.parent()
|
importPath.isAllUnder && !isRoot -> importPath.fqnPart() == this.parent()
|
||||||
else -> importPath.fqnPart() == this
|
else -> importPath.fqnPart() == this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun ImportPath.isImported(alreadyImported: ImportPath): Boolean {
|
fun ImportPath.isImported(alreadyImported: ImportPath): Boolean {
|
||||||
return if (isAllUnder() || hasAlias()) this == alreadyImported else fqnPart().isImported(alreadyImported)
|
return if (isAllUnder || hasAlias()) this == alreadyImported else fqnPart().isImported(alreadyImported)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun ImportPath.isImported(imports: Iterable<ImportPath>): Boolean = imports.any { isImported(it) }
|
fun ImportPath.isImported(imports: Iterable<ImportPath>): Boolean = imports.any { isImported(it) }
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user