Support checking ArrayValue compile-time constants

This commit is contained in:
Him188 2020-09-18 23:58:01 +08:00
parent 4c0daefd67
commit 56a7098627
3 changed files with 28 additions and 15 deletions

View File

@ -9,7 +9,7 @@
object Versions { object Versions {
const val core = "1.3.0" const val core = "1.3.0"
const val console = "1.0-RC-dev-3" const val console = "1.0-RC-dev-4"
const val consoleGraphical = "0.0.7" const val consoleGraphical = "0.0.7"
const val consoleTerminal = console const val consoleTerminal = console

View File

@ -14,7 +14,7 @@ import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors
import net.mamoe.mirai.console.compiler.common.resolve.ResolveContextKind import net.mamoe.mirai.console.compiler.common.resolve.ResolveContextKind
import net.mamoe.mirai.console.compiler.common.resolve.resolveContextKind import net.mamoe.mirai.console.compiler.common.resolve.resolveContextKind
import net.mamoe.mirai.console.intellij.resolve.resolveAllCalls import net.mamoe.mirai.console.intellij.resolve.resolveAllCalls
import net.mamoe.mirai.console.intellij.resolve.resolveStringConstantValue import net.mamoe.mirai.console.intellij.resolve.resolveStringConstantValues
import net.mamoe.mirai.console.intellij.resolve.valueParametersWithArguments import net.mamoe.mirai.console.intellij.resolve.valueParametersWithArguments
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Diagnostic
@ -93,12 +93,14 @@ class ContextualParametersChecker : DeclarationChecker {
p.resolveContextKind?.let(checkersMap::get)?.let { it to a } p.resolveContextKind?.let(checkersMap::get)?.let { it to a }
} }
.mapNotNull { (kind, argument) -> .mapNotNull { (kind, argument) ->
argument.resolveStringConstantValue(context.bindingContext)?.let { const -> argument.resolveStringConstantValues()?.let { const ->
Triple(kind, argument, const) Triple(kind, argument, const)
} }
} }
.forEach { (fn, argument, resolvedConstant) -> .forEach { (fn, argument, resolvedConstants) ->
fn(argument.asElement(), resolvedConstant)?.let { context.report(it) } for (resolvedConstant in resolvedConstants) {
fn(argument.asElement(), resolvedConstant)?.let { context.report(it) }
}
} }
return return
} }

View File

@ -30,6 +30,8 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
@ -106,8 +108,8 @@ fun ResolvedCall<*>.valueParametersWithArguments(): List<Pair<ValueParameterDesc
return this.valueParameters.zip(this.valueArgumentsByIndex?.mapNotNull { it.arguments.firstOrNull() }.orEmpty()) return this.valueParameters.zip(this.valueArgumentsByIndex?.mapNotNull { it.arguments.firstOrNull() }.orEmpty())
} }
fun ValueArgument.resolveStringConstantValue(bindingContext: BindingContext): String? { fun ValueArgument.resolveStringConstantValues(): Sequence<String>? {
return this.getArgumentExpression()?.resolveStringConstantValue(bindingContext) return this.getArgumentExpression()?.resolveStringConstantValues()
} }
val PsiElement.allChildrenFlat: Sequence<PsiElement> val PsiElement.allChildrenFlat: Sequence<PsiElement>
@ -131,14 +133,24 @@ fun KtElement?.getResolvedCallOrResolveToCall(
val ResolvedCall<out CallableDescriptor>.valueParameters: List<ValueParameterDescriptor> get() = this.resultingDescriptor.valueParameters val ResolvedCall<out CallableDescriptor>.valueParameters: List<ValueParameterDescriptor> get() = this.resultingDescriptor.valueParameters
fun KtExpression.resolveStringConstantValue(bindingContext: BindingContext): String? { fun ConstantValue<*>.selfOrChildrenConstantStrings(): Sequence<String> {
return when (this) {
is StringValue -> sequenceOf(value)
is ArrayValue -> sequence {
yieldAll(this@selfOrChildrenConstantStrings.selfOrChildrenConstantStrings())
}
else -> emptySequence()
}
}
fun KtExpression.resolveStringConstantValues(): Sequence<String> {
when (this) { when (this) {
is KtNameReferenceExpression -> { is KtNameReferenceExpression -> {
when (val reference = references.firstIsInstance<KtSimpleNameReference>().resolve()) { when (val reference = references.firstIsInstance<KtSimpleNameReference>().resolve()) {
is KtDeclaration -> { is KtDeclaration -> {
val descriptor = reference.descriptor.castOrNull<VariableDescriptor>() ?: return null val descriptor = reference.descriptor.castOrNull<VariableDescriptor>() ?: return emptySequence()
val compileTimeConstant = descriptor.compileTimeInitializer ?: return null val compileTimeConstant = descriptor.compileTimeInitializer ?: return emptySequence()
return compileTimeConstant.castOrNull<StringValue>()?.value return compileTimeConstant.selfOrChildrenConstantStrings()
} }
is PsiDeclarationStatement -> { is PsiDeclarationStatement -> {
// TODO: 2020/9/18 compile-time constants from Java // TODO: 2020/9/18 compile-time constants from Java
@ -146,8 +158,8 @@ fun KtExpression.resolveStringConstantValue(bindingContext: BindingContext): Str
} }
} }
is KtStringTemplateExpression -> { is KtStringTemplateExpression -> {
if (hasInterpolation()) return null if (hasInterpolation()) return emptySequence()
return entries.joinToString("") { it.text } return sequenceOf(entries.joinToString("") { it.text })
} }
/* /*
is KtCallExpression -> { is KtCallExpression -> {
@ -161,7 +173,6 @@ fun KtExpression.resolveStringConstantValue(bindingContext: BindingContext): Str
is KtConstantExpression -> { is KtConstantExpression -> {
// TODO: 2020/9/18 KtExpression.resolveStringConstantValue: KtConstantExpression // TODO: 2020/9/18 KtExpression.resolveStringConstantValue: KtConstantExpression
} }
else -> return null
} }
return null return emptySequence()
} }