Merge remote-tracking branch 'console/master'

This commit is contained in:
Him188 2021-02-24 09:09:21 +08:00
commit a2e7112cd3
14 changed files with 208 additions and 41 deletions

View File

@ -17,9 +17,13 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start
import net.mamoe.mirai.console.command.ConsoleCommandSender import net.mamoe.mirai.console.command.ConsoleCommandSender
import net.mamoe.mirai.console.data.PluginDataStorage import net.mamoe.mirai.console.data.PluginDataStorage
import net.mamoe.mirai.console.extension.ComponentStorage
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
import net.mamoe.mirai.console.internal.logging.LoggerControllerImpl import net.mamoe.mirai.console.internal.logging.LoggerControllerImpl
import net.mamoe.mirai.console.internal.plugin.PluginManagerImpl
import net.mamoe.mirai.console.logging.LoggerController import net.mamoe.mirai.console.logging.LoggerController
import net.mamoe.mirai.console.plugin.Plugin
import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader import net.mamoe.mirai.console.plugin.jvm.JvmPluginLoader
import net.mamoe.mirai.console.plugin.loader.PluginLoader import net.mamoe.mirai.console.plugin.loader.PluginLoader
import net.mamoe.mirai.console.util.ConsoleInput import net.mamoe.mirai.console.util.ConsoleInput
@ -185,8 +189,72 @@ public interface MiraiConsoleImplementation : CoroutineScope {
public val loggerController: LoggerController get() = LoggerControllerImpl public val loggerController: LoggerController get() = LoggerControllerImpl
/// Hooks & Backend Access
/**
* 后端 [phase] 阶段执行前会调用此方法, 如果此方法抛出了一个错误会直接中断 console 初始化
*
* @since 2.5.0-dev-2
*/
public fun prePhase(phase: String) {}
/**
* 后端 [phase] 阶段执行后会调用此方法, 如果此方法抛出了一个错误会直接中断 console 初始化
*
* @since 2.5.0-dev-2
*/
public fun postPhase(phase: String) {}
/**
* 后端在 [start] 前会调用此方法
*
* @since 2.5.0-dev-2
*/
public fun preStart() {}
/**
* 后端在 [start] 后会调用此方法
*
* @since 2.5.0-dev-2
*/
public fun postStart() {}
/**
* 前端访问后端内部实现的桥
*
* @see backendAccess
* @since 2.5.0-dev-2
*/
@ConsoleFrontEndImplementation
public interface BackendAccess {
// GlobalComponentStorage
public val globalComponentStorage: ComponentStorage
// PluginManagerImpl.resolvedPlugins
public val resolvedPlugins: MutableList<Plugin>
}
/**
* @see BackendAccess
* @since 2.5.0-dev-2
* @throws IllegalStateException 当前端实例不是 `this` 时抛出
*/
public val backendAccess: BackendAccess
get() {
if (instanceInitialized) {
if (this === instance)
return backendAccessInstance
}
throw IllegalStateException("Permission denied")
}
public companion object { public companion object {
private val backendAccessInstance = object : BackendAccess {
override val globalComponentStorage: ComponentStorage get() = GlobalComponentStorage
override val resolvedPlugins: MutableList<Plugin> get() = PluginManagerImpl.resolvedPlugins
}
internal lateinit var instance: MiraiConsoleImplementation internal lateinit var instance: MiraiConsoleImplementation
internal val instanceInitialized: Boolean get() = ::instance.isInitialized
private val initLock = ReentrantLock() private val initLock = ReentrantLock()
/** /**

View File

@ -37,6 +37,7 @@ import net.mamoe.mirai.console.permission.PermissionService
import net.mamoe.mirai.console.permission.PermissionService.Companion.cancel import net.mamoe.mirai.console.permission.PermissionService.Companion.cancel
import net.mamoe.mirai.console.permission.PermissionService.Companion.findCorrespondingPermissionOrFail import net.mamoe.mirai.console.permission.PermissionService.Companion.findCorrespondingPermissionOrFail
import net.mamoe.mirai.console.permission.PermissionService.Companion.getPermittedPermissions import net.mamoe.mirai.console.permission.PermissionService.Companion.getPermittedPermissions
import net.mamoe.mirai.console.permission.PermissionService.Companion.hasPermission
import net.mamoe.mirai.console.permission.PermissionService.Companion.permit import net.mamoe.mirai.console.permission.PermissionService.Companion.permit
import net.mamoe.mirai.console.permission.PermitteeId import net.mamoe.mirai.console.permission.PermitteeId
import net.mamoe.mirai.console.plugin.name import net.mamoe.mirai.console.plugin.name
@ -98,6 +99,7 @@ public object BuiltInCommands {
public suspend fun CommandSender.handle() { public suspend fun CommandSender.handle() {
sendMessage( sendMessage(
allRegisteredCommands allRegisteredCommands
.filter { hasPermission(it.permission) }
.joinToString("\n\n") { command -> .joinToString("\n\n") { command ->
val lines = command.usage.lines() val lines = command.usage.lines()
if (lines.isEmpty()) "/${command.primaryName} ${command.description}" if (lines.isEmpty()) "/${command.primaryName} ${command.description}"

View File

@ -121,7 +121,7 @@ public abstract class CompositeCommand(
@Retention(RUNTIME) @Retention(RUNTIME)
@Target(FUNCTION) @Target(FUNCTION)
protected annotation class SubCommand( protected annotation class SubCommand(
@ResolveContext(COMMAND_NAME) vararg val value: String, @ResolveContext(COMMAND_NAME) vararg val value: String = [],
) )
/** 指令描述 */ /** 指令描述 */

View File

@ -14,8 +14,8 @@ import java.time.Instant
internal object MiraiConsoleBuildConstants { // auto-filled on build (task :mirai-console:fillBuildConstants) internal object MiraiConsoleBuildConstants { // auto-filled on build (task :mirai-console:fillBuildConstants)
@JvmStatic @JvmStatic
val buildDate: Instant = Instant.ofEpochSecond(1613042196) val buildDate: Instant = Instant.ofEpochSecond(1613308312)
const val versionConst: String = "2.4-RC" const val versionConst: String = "2.4.0"
@JvmStatic @JvmStatic
val version: SemVersion = SemVersion(versionConst) val version: SemVersion = SemVersion(versionConst)

View File

@ -16,7 +16,10 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.console.* import net.mamoe.mirai.console.MalformedMiraiConsoleImplementationError
import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.MiraiConsoleFrontEndDescription
import net.mamoe.mirai.console.MiraiConsoleImplementation
import net.mamoe.mirai.console.command.BuiltInCommands import net.mamoe.mirai.console.command.BuiltInCommands
import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.command.CommandManager
import net.mamoe.mirai.console.command.ConsoleCommandSender import net.mamoe.mirai.console.command.ConsoleCommandSender
@ -104,8 +107,9 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
@Suppress("RemoveRedundantBackticks") @Suppress("RemoveRedundantBackticks")
internal fun doStart() { internal fun doStart() {
instance.preStart()
phase `setup logger controller`@{ phase("setup logger controller") {
if (loggerController === LoggerControllerImpl) { if (loggerController === LoggerControllerImpl) {
// Reload LoggerConfig. // Reload LoggerConfig.
ConsoleDataScope.addAndReloadConfig(LoggerConfig) ConsoleDataScope.addAndReloadConfig(LoggerConfig)
@ -113,7 +117,7 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
} }
} }
phase `greeting`@{ phase("greeting") {
val buildDateFormatted = val buildDateFormatted =
buildDate.atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) buildDate.atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
@ -122,7 +126,7 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
mainLogger.info { frontEndDescription.render() } mainLogger.info { frontEndDescription.render() }
} }
phase `check coroutineContext`@{ phase("check coroutineContext") {
if (coroutineContext[Job] == null) { if (coroutineContext[Job] == null) {
throw MalformedMiraiConsoleImplementationError("The coroutineContext given to MiraiConsole must have a Job in it.") throw MalformedMiraiConsoleImplementationError("The coroutineContext given to MiraiConsole must have a Job in it.")
} }
@ -139,13 +143,13 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
// start // start
phase `load configurations`@{ phase("load configurations") {
mainLogger.verbose { "Loading configurations..." } mainLogger.verbose { "Loading configurations..." }
ConsoleDataScope.addAndReloadConfig(CommandConfig) ConsoleDataScope.addAndReloadConfig(CommandConfig)
ConsoleDataScope.reloadAll() ConsoleDataScope.reloadAll()
} }
phase `initialize all plugins`@{ phase("initialize all plugins") {
PluginManager // init PluginManager // init
mainLogger.verbose { "Loading JVM plugins..." } mainLogger.verbose { "Loading JVM plugins..." }
@ -158,13 +162,13 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
} }
} }
phase `load all plugins`@{ phase("load all plugins") {
PluginManagerImpl.loadPlugins(PluginManagerImpl.scanPluginsUsingPluginLoadersIncludingThoseFromPluginLoaderProvider()) PluginManagerImpl.loadPlugins(PluginManagerImpl.scanPluginsUsingPluginLoadersIncludingThoseFromPluginLoaderProvider())
mainLogger.verbose { "${PluginManager.plugins.size} plugin(s) loaded." } mainLogger.verbose { "${PluginManager.plugins.size} plugin(s) loaded." }
} }
phase `load SingletonExtensionSelector`@{ phase("load SingletonExtensionSelector") {
SingletonExtensionSelector.init() SingletonExtensionSelector.init()
val instance = SingletonExtensionSelector.instance val instance = SingletonExtensionSelector.instance
if (instance is BuiltInSingletonExtensionSelector) { if (instance is BuiltInSingletonExtensionSelector) {
@ -173,7 +177,7 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
} }
phase `load PermissionService`@{ phase("load PermissionService") {
mainLogger.verbose { "Loading PermissionService..." } mainLogger.verbose { "Loading PermissionService..." }
PermissionService.INSTANCE.let { ps -> PermissionService.INSTANCE.let { ps ->
@ -188,7 +192,7 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
runIgnoreException<UnsupportedOperationException> { ConsoleCommandSender.permit(RootPermission) } runIgnoreException<UnsupportedOperationException> { ConsoleCommandSender.permit(RootPermission) }
} }
phase `prepare commands`@{ phase("prepare commands") {
mainLogger.verbose { "Loading built-in commands..." } mainLogger.verbose { "Loading built-in commands..." }
BuiltInCommands.registerAll() BuiltInCommands.registerAll()
mainLogger.info { "Prepared built-in commands: ${BuiltInCommands.all.joinToString { it.primaryName }}" } mainLogger.info { "Prepared built-in commands: ${BuiltInCommands.all.joinToString { it.primaryName }}" }
@ -196,7 +200,7 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
// CommandManagerImpl.commandListener // start // CommandManagerImpl.commandListener // start
} }
phase `enable plugins`@{ phase("enable plugins") {
mainLogger.verbose { "Enabling plugins..." } mainLogger.verbose { "Enabling plugins..." }
PluginManagerImpl.enableAllLoadedPlugins() PluginManagerImpl.enableAllLoadedPlugins()
@ -208,7 +212,7 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
mainLogger.info { "${PluginManagerImpl.plugins.size} plugin(s) enabled." } mainLogger.info { "${PluginManagerImpl.plugins.size} plugin(s) enabled." }
} }
phase `auto-login bots`@{ phase("auto-login bots") {
runBlocking { runBlocking {
val accounts = AutoLoginConfig.accounts.toList() val accounts = AutoLoginConfig.accounts.toList()
for (account in accounts) { for (account in accounts) {
@ -259,9 +263,13 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
} }
} }
phase("finally post") {
GlobalComponentStorage.run { GlobalComponentStorage.run {
PostStartupExtension.useExtensions { it() } // exceptions thrown will be caught by caller of `doStart`. PostStartupExtension.useExtensions { it() } // exceptions thrown will be caught by caller of `doStart`.
} }
}
instance.postStart()
mainLogger.info { "mirai-console started successfully." } mainLogger.info { "mirai-console started successfully." }
} }
@ -275,10 +283,20 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
* 表示一个初始化阶段, 无实际作用. * 表示一个初始化阶段, 无实际作用.
*/ */
@ILoveOmaeKumikoForever @ILoveOmaeKumikoForever
private inline fun phase(block: () -> Unit) { private inline fun phase(phase: String, block: () -> Unit) {
contract { contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE) callsInPlace(block, InvocationKind.EXACTLY_ONCE)
} }
prePhase(phase)
block() block()
postPhase(phase)
}
override fun prePhase(phase: String) {
instance.prePhase(phase)
}
override fun postPhase(phase: String) {
instance.postPhase(phase)
} }
} }

View File

@ -203,10 +203,12 @@ internal class CommandReflector(
) )
fun CommandParameter<*>.toErasedParameterInfo(index: Int): ErasedParameterInfo { fun CommandParameter<*>.toErasedParameterInfo(index: Int): ErasedParameterInfo {
return ErasedParameterInfo(index, return ErasedParameterInfo(
index,
this.name, this.name,
this.type.withNullability(false), this.type.withNullability(false),
if (this is AbstractCommandValueParameter.StringConstant) this.expectingValue else null) if (this is AbstractCommandValueParameter.StringConstant) this.expectingValue else null
)
} }
val candidates = signatures.map { variant -> val candidates = signatures.map { variant ->
@ -244,11 +246,21 @@ internal class CommandReflector(
name?.split(' ')?.mapIndexed { index, s -> createStringConstantParameterForName(index, s) } name?.split(' ')?.mapIndexed { index, s -> createStringConstantParameterForName(index, s) }
.orEmpty() .orEmpty()
val valueParameters = function.valueParameters.toMutableList()
var receiverParameter = function.extensionReceiverParameter
if (receiverParameter == null && valueParameters.isNotEmpty()) {
val valueFirstParameter = valueParameters[0]
if (valueFirstParameter.type.classifierAsKClassOrNull()?.isSubclassOf(CommandSender::class) == true) {
receiverParameter = valueFirstParameter
valueParameters.removeAt(0)
}
}
val functionValueParameters = val functionValueParameters =
function.valueParameters.associateBy { it.toUserDefinedCommandParameter() } valueParameters.associateBy { it.toUserDefinedCommandParameter() }
CommandSignatureFromKFunctionImpl( CommandSignatureFromKFunctionImpl(
receiverParameter = function.extensionReceiverParameter?.toCommandReceiverParameter(), receiverParameter = receiverParameter?.toCommandReceiverParameter(),
valueParameters = functionNameAsValueParameter + functionValueParameters.keys, valueParameters = functionNameAsValueParameter + functionValueParameters.keys,
originFunction = function originFunction = function
) { call -> ) { call ->
@ -272,7 +284,6 @@ internal class CommandReflector(
args[instanceParameter] = command args[instanceParameter] = command
} }
val receiverParameter = function.extensionReceiverParameter
if (receiverParameter != null) { if (receiverParameter != null) {
check(receiverParameter.type.classifierAsKClass().isInstance(call.caller)) { check(receiverParameter.type.classifierAsKClass().isInstance(call.caller)) {
"Bad command call resolved. " + "Bad command call resolved. " +

View File

@ -14,7 +14,6 @@ package net.mamoe.mirai.console.internal.util
import net.mamoe.mirai.console.internal.data.cast import net.mamoe.mirai.console.internal.data.cast
import net.mamoe.mirai.console.internal.data.createInstanceOrNull import net.mamoe.mirai.console.internal.data.createInstanceOrNull
import net.mamoe.mirai.console.internal.plugin.BuiltInJvmPluginLoaderImpl import net.mamoe.mirai.console.internal.plugin.BuiltInJvmPluginLoaderImpl
import java.io.InputStream
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import java.util.* import java.util.*
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -30,9 +29,13 @@ internal object PluginServiceHelper {
fun <T : Any> ClassLoader.findServices(vararg serviceTypes: KClass<out T>): ServiceList<T> = fun <T : Any> ClassLoader.findServices(vararg serviceTypes: KClass<out T>): ServiceList<T> =
serviceTypes.flatMap { serviceType -> serviceTypes.flatMap { serviceType ->
getResourceAsStream("META-INF/services/" + serviceType.qualifiedName!!) getResourceAsStream("META-INF/services/" + serviceType.qualifiedName!!)?.let { stream ->
?.use(InputStream::readBytes) stream.bufferedReader().useLines { lines ->
?.let(::String)?.lines()?.filter(String::isNotBlank).orEmpty() lines.filter(String::isNotBlank)
.filter { it[0] != '#' }
.toList()
}
}.orEmpty()
}.let { ServiceList(this, it) } }.let { ServiceList(this, it) }
fun <T : Any> ServiceList<T>.loadAllServices(): List<T> { fun <T : Any> ServiceList<T>.loadAllServices(): List<T> {

View File

@ -69,9 +69,11 @@ object TestEnumArgCommand : CompositeCommand(owner, "testenum") {
enum class TestEnum { enum class TestEnum {
V1, V2, V3 V1, V2, V3
} }
enum class TestCase { enum class TestCase {
A, a A, a
} }
enum class TestCamelCase { enum class TestCamelCase {
A, B, A_B A, B, A_B
} }
@ -295,6 +297,36 @@ internal class TestCommand {
} }
} }
@Test
fun `test first param command sender`() = runBlocking<Unit> {
object : CompositeCommand(owner, "cmd") {
@SubCommand
fun handle(sender: CommandSender, arg: String) {
Testing.ok(arg)
}
}.withRegistration {
assertEquals("test", withTesting { assertSuccess(execute(sender, "handle test")) })
}
object : SimpleCommand(owner, "cmd") {
@Handler
fun handle(sender: CommandSender, arg: String) {
Testing.ok(arg)
}
}.withRegistration {
assertEquals("hello", withTesting { assertSuccess(execute(sender, "hello")) })
}
object : SimpleCommand(owner, "cmd") {
@Handler
fun handle(arg: String, sender: CommandSender) {
Testing.ok(arg)
}
}.withRegistration {
assertFailure(execute(sender, "hello"))
}
}
@Test @Test
fun `composite sub command resolution conflict`() { fun `composite sub command resolution conflict`() {
runBlocking { runBlocking {

View File

@ -1,3 +1,12 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress("UnstableApiUsage") @file:Suppress("UnstableApiUsage")
import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.dsl.*
@ -26,7 +35,6 @@ allprojects {
maven(url = "https://dl.bintray.com/kotlin/kotlin-eap") maven(url = "https://dl.bintray.com/kotlin/kotlin-eap")
jcenter() jcenter()
mavenCentral() mavenCentral()
maven(url = "https://dl.bintray.com/karlatemp/misc")
} }
} }

View File

@ -63,7 +63,7 @@ const val yamlkt = "net.mamoe.yamlkt:yamlkt:${Versions.yamlkt}"
const val `jetbrains-annotations` = "org.jetbrains:annotations:19.0.0" const val `jetbrains-annotations` = "org.jetbrains:annotations:19.0.0"
const val `caller-finder` = "io.github.karlatemp:caller:1.0.1" const val `caller-finder` = "io.github.karlatemp:caller:1.1.1"
val ATTRIBUTE_MIRAI_TARGET_PLATFORM: Attribute<String> = Attribute.of("mirai.target.platform", String::class.java) val ATTRIBUTE_MIRAI_TARGET_PLATFORM: Attribute<String> = Attribute.of("mirai.target.platform", String::class.java)

View File

@ -10,6 +10,6 @@
package net.mamoe.mirai.console.gradle package net.mamoe.mirai.console.gradle
internal object VersionConstants { internal object VersionConstants {
const val CONSOLE_VERSION = "2.4-RC" // value is written here automatically during build const val CONSOLE_VERSION = "2.4.0" // value is written here automatically during build
const val CORE_VERSION = "2.4-RC" // value is written here automatically during build const val CORE_VERSION = "2.4.0" // value is written here automatically during build
} }

View File

@ -11,7 +11,19 @@ import java.io.IOException;
import static org.example.myplugin.ResourceNotClosedInspectionTestKt.magic; import static org.example.myplugin.ResourceNotClosedInspectionTestKt.magic;
public class ResourceNotClosedInspectionTestJava { public class ResourceNotClosedInspectionTestJava {
public static Object funA() {
return new Object();
}
public static void funB(Object obj) {
System.out.println(obj);
}
public static void main(String[] args) { public static void main(String[] args) {
// https://github.com/mamoe/mirai-console/issues/294
funB(funA());
File file = magic(); File file = magic();
Contact contact = magic(); Contact contact = magic();

View File

@ -3,6 +3,7 @@ package test;
import net.mamoe.mirai.console.command.Command; import net.mamoe.mirai.console.command.Command;
import net.mamoe.mirai.console.command.CommandOwner; import net.mamoe.mirai.console.command.CommandOwner;
import net.mamoe.mirai.console.command.descriptor.CommandSignatureFromKFunction; import net.mamoe.mirai.console.command.descriptor.CommandSignatureFromKFunction;
import net.mamoe.mirai.console.command.java.JCompositeCommand;
import net.mamoe.mirai.console.command.java.JSimpleCommand; import net.mamoe.mirai.console.command.java.JSimpleCommand;
import net.mamoe.mirai.console.permission.Permission; import net.mamoe.mirai.console.permission.Permission;
import net.mamoe.mirai.console.plugin.jvm.JavaPlugin; import net.mamoe.mirai.console.plugin.jvm.JavaPlugin;
@ -28,3 +29,16 @@ class TestCommand extends JSimpleCommand {
} }
} }
class TestCommand2 extends JCompositeCommand {
public TestCommand2(@NotNull CommandOwner owner, @NotNull String primaryName, @NotNull String[] secondaryNames, @NotNull Permission parentPermission) {
super(owner, primaryName, secondaryNames, parentPermission);
}
@SubCommand("test")
public void test() {}
@SubCommand({})
public void subCmd() {
}
}

View File

@ -96,16 +96,21 @@ fun KtFunction.hasSignature(functionSignature: FunctionSignature): Boolean {
return true return true
} }
fun KtLightMethod.hasSignature(functionSignature: FunctionSignature): Boolean {
fun PsiMethod.hasSignature(functionSignature: FunctionSignature): Boolean {
if (functionSignature.name != null) { if (functionSignature.name != null) {
if (this.name != functionSignature.name) return false if (this.name != functionSignature.name) return false
} }
val parameters = parameterList.parameters.toMutableList() val parameters = parameterList.parameters.toMutableList()
if (functionSignature.dispatchReceiver != null) { if (functionSignature.dispatchReceiver != null) {
val kotlinContainingClassFqn = val containingClass = this.containingClass ?: return false
val kotlinContainingClassFqn = if (this is KtLightMethod) {
if (this.modifierList.hasExplicitModifier(PsiModifier.STATIC)) { if (this.modifierList.hasExplicitModifier(PsiModifier.STATIC)) {
this.containingClass.kotlinOrigin?.companionObjects?.firstOrNull()?.fqName this.containingClass.kotlinOrigin?.companionObjects?.firstOrNull()?.fqName
} else this.containingClass.getKotlinFqName() } else containingClass.getKotlinFqName()
} else containingClass.getKotlinFqName()
if (kotlinContainingClassFqn != functionSignature.dispatchReceiver) return false if (kotlinContainingClassFqn != functionSignature.dispatchReceiver) return false
} }
if (functionSignature.extensionReceiver != null) { if (functionSignature.extensionReceiver != null) {
@ -121,12 +126,6 @@ fun KtLightMethod.hasSignature(functionSignature: FunctionSignature): Boolean {
return true return true
} }
fun PsiMethod.hasSignature(functionSignature: FunctionSignature): Boolean {
if (this is KtLightMethod) {
return this.hasSignature(functionSignature)
}
return true
}
fun KtExpression.isCalling(functionSignature: FunctionSignature): Boolean { fun KtExpression.isCalling(functionSignature: FunctionSignature): Boolean {
val descriptor = resolveToCall(BodyResolveMode.PARTIAL)?.resultingDescriptor ?: return false val descriptor = resolveToCall(BodyResolveMode.PARTIAL)?.resultingDescriptor ?: return false