KT-17074: Make completion respect DslMarker's
#KT-17074 fixed
This commit is contained in:
+11
-10
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.resolve.calls.checkers
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
@@ -31,6 +30,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
object DslScopeViolationCallChecker : CallChecker {
|
object DslScopeViolationCallChecker : CallChecker {
|
||||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||||
@@ -55,28 +55,29 @@ object DslScopeViolationCallChecker : CallChecker {
|
|||||||
|
|
||||||
if (receiversUntilOneFromTheCall.isEmpty()) return
|
if (receiversUntilOneFromTheCall.isEmpty()) return
|
||||||
|
|
||||||
val callDslMarkers = callImplicitReceiver.extractDslMarkerFqNames()
|
val callDslMarkers = callImplicitReceiver.type.extractDslMarkerFqNames()
|
||||||
if (callDslMarkers.isEmpty()) return
|
if (callDslMarkers.isEmpty()) return
|
||||||
|
|
||||||
val closestAnotherReceiverWithSameDslMarker =
|
val closestAnotherReceiverWithSameDslMarker =
|
||||||
receiversUntilOneFromTheCall.firstOrNull { receiver -> receiver.extractDslMarkerFqNames().any(callDslMarkers::contains) }
|
receiversUntilOneFromTheCall.firstOrNull { receiver -> receiver.type.extractDslMarkerFqNames().any(callDslMarkers::contains) }
|
||||||
|
|
||||||
if (closestAnotherReceiverWithSameDslMarker != null) {
|
if (closestAnotherReceiverWithSameDslMarker != null) {
|
||||||
// TODO: report receivers configuration (what's one is used and what's one is the closest)
|
// TODO: report receivers configuration (what's one is used and what's one is the closest)
|
||||||
context.trace.report(Errors.DSL_SCOPE_VIOLATION.on(reportOn, resolvedCall.resultingDescriptor))
|
context.trace.report(Errors.DSL_SCOPE_VIOLATION.on(reportOn, resolvedCall.resultingDescriptor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun ReceiverValue.extractDslMarkerFqNames(): Set<FqName> {
|
fun KotlinType.extractDslMarkerFqNames(): Set<FqName> {
|
||||||
val result = mutableSetOf<FqName>()
|
val result = mutableSetOf<FqName>()
|
||||||
|
|
||||||
result.addAll(type.annotations.extractDslMarkerFqNames())
|
result.addAll(annotations.extractDslMarkerFqNames())
|
||||||
|
|
||||||
type.constructor.declarationDescriptor?.getAllSuperClassifiers()?.asIterable()
|
constructor.declarationDescriptor?.getAllSuperClassifiers()?.asIterable()
|
||||||
?.flatMapTo(result) { it.annotations.extractDslMarkerFqNames() }
|
?.flatMapTo(result) { it.annotations.extractDslMarkerFqNames() }
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Annotations.extractDslMarkerFqNames() =
|
private fun Annotations.extractDslMarkerFqNames() =
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ sealed class CallTypeAndReceiver<TReceiver : KtElement?, out TCallType : CallTyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ReceiverType(val type: KotlinType, val receiverIndex: Int)
|
data class ReceiverType(val type: KotlinType, val receiverIndex: Int, val implicit: Boolean = false)
|
||||||
|
|
||||||
fun CallTypeAndReceiver<*, *>.receiverTypes(
|
fun CallTypeAndReceiver<*, *>.receiverTypes(
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
@@ -227,7 +227,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
|
|||||||
contextElement: PsiElement,
|
contextElement: PsiElement,
|
||||||
moduleDescriptor: ModuleDescriptor,
|
moduleDescriptor: ModuleDescriptor,
|
||||||
resolutionFacade: ResolutionFacade,
|
resolutionFacade: ResolutionFacade,
|
||||||
stableSmartCastsOnly: Boolean
|
stableSmartCastsOnly: Boolean,
|
||||||
|
withImplicitReceiversWhenExplicitPresent: Boolean = false
|
||||||
): Collection<ReceiverType>? {
|
): Collection<ReceiverType>? {
|
||||||
val receiverExpression: KtExpression?
|
val receiverExpression: KtExpression?
|
||||||
when (this) {
|
when (this) {
|
||||||
@@ -279,25 +280,35 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
|
|||||||
else -> throw RuntimeException() //TODO: see KT-9394
|
else -> throw RuntimeException() //TODO: see KT-9394
|
||||||
}
|
}
|
||||||
|
|
||||||
val receiverValues = if (receiverExpression != null) {
|
val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
|
||||||
|
|
||||||
|
val expressionReceiver = receiverExpression?.let {
|
||||||
val receiverType =
|
val receiverType =
|
||||||
bindingContext.getType(receiverExpression) ?:
|
bindingContext.getType(receiverExpression) ?:
|
||||||
(bindingContext.get(BindingContext.QUALIFIER, receiverExpression) as? ClassQualifier)?.descriptor?.classValueType ?:
|
(bindingContext.get(BindingContext.QUALIFIER, receiverExpression) as? ClassQualifier)?.descriptor?.classValueType ?:
|
||||||
(bindingContext.get(BindingContext.QUALIFIER, receiverExpression) as? TypeAliasQualifier)?.classDescriptor?.classValueType ?:
|
(bindingContext.get(BindingContext.QUALIFIER, receiverExpression) as? TypeAliasQualifier)?.classDescriptor?.classValueType ?:
|
||||||
return emptyList()
|
return emptyList()
|
||||||
listOf(ExpressionReceiver.create(receiverExpression, receiverType, bindingContext))
|
ExpressionReceiver.create(receiverExpression, receiverType, bindingContext)
|
||||||
}
|
|
||||||
else {
|
|
||||||
val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
|
|
||||||
resolutionScope.getImplicitReceiversWithInstance().map { it.value }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val implicitReceiverValues = resolutionScope.getImplicitReceiversWithInstance().map { it.value }
|
||||||
|
|
||||||
val dataFlowInfo = bindingContext.getDataFlowInfoBefore(contextElement)
|
val dataFlowInfo = bindingContext.getDataFlowInfoBefore(contextElement)
|
||||||
|
|
||||||
val result = ArrayList<ReceiverType>()
|
val result = ArrayList<ReceiverType>()
|
||||||
for ((receiverIndex, receiverValue) in receiverValues.withIndex()) {
|
|
||||||
|
var receiverIndex = 0
|
||||||
|
|
||||||
|
fun addReceiverType(receiverValue: ReceiverValue, implicit: Boolean) {
|
||||||
val types = receiverValueTypes(receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly)
|
val types = receiverValueTypes(receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly)
|
||||||
types.mapTo(result) { ReceiverType(it, receiverIndex) }
|
types.mapTo(result) { ReceiverType(it, receiverIndex, implicit) }
|
||||||
|
receiverIndex++
|
||||||
|
}
|
||||||
|
if (withImplicitReceiversWhenExplicitPresent || expressionReceiver == null) {
|
||||||
|
implicitReceiverValues.forEach { addReceiverType(it, true) }
|
||||||
|
}
|
||||||
|
if (expressionReceiver != null) {
|
||||||
|
addReceiverType(expressionReceiver, false)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import com.intellij.patterns.PatternCondition
|
|||||||
import com.intellij.patterns.StandardPatterns
|
import com.intellij.patterns.StandardPatterns
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.ModuleOrigin
|
import org.jetbrains.kotlin.idea.caches.resolve.ModuleOrigin
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.OriginCapability
|
import org.jetbrains.kotlin.idea.caches.resolve.OriginCapability
|
||||||
@@ -36,10 +37,13 @@ import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
|||||||
import org.jetbrains.kotlin.idea.core.*
|
import org.jetbrains.kotlin.idea.core.*
|
||||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||||
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
|
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
|
||||||
|
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.util.*
|
import org.jetbrains.kotlin.idea.util.*
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.checkers.DslScopeViolationCallChecker.extractDslMarkerFqNames
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
@@ -48,6 +52,7 @@ import org.jetbrains.kotlin.types.TypeUtils
|
|||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.LinkedHashMap
|
||||||
|
|
||||||
class CompletionSessionConfiguration(
|
class CompletionSessionConfiguration(
|
||||||
val useBetterPrefixMatcherForNonImportedClasses: Boolean,
|
val useBetterPrefixMatcherForNonImportedClasses: Boolean,
|
||||||
@@ -374,12 +379,30 @@ abstract class CompletionSession(
|
|||||||
callTypeAndReceiver: CallTypeAndReceiver<*, *>): Collection<ReceiverType>? {
|
callTypeAndReceiver: CallTypeAndReceiver<*, *>): Collection<ReceiverType>? {
|
||||||
var receiverTypes = callTypeAndReceiver.receiverTypesWithIndex(
|
var receiverTypes = callTypeAndReceiver.receiverTypesWithIndex(
|
||||||
bindingContext, nameExpression, moduleDescriptor, resolutionFacade,
|
bindingContext, nameExpression, moduleDescriptor, resolutionFacade,
|
||||||
stableSmartCastsOnly = true /* we don't include smart cast receiver types for "unstable" receiver value to mark members grayed */)
|
stableSmartCastsOnly = true, /* we don't include smart cast receiver types for "unstable" receiver value to mark members grayed */
|
||||||
|
withImplicitReceiversWhenExplicitPresent = true)
|
||||||
|
|
||||||
if (callTypeAndReceiver is CallTypeAndReceiver.SAFE || isDebuggerContext) {
|
if (callTypeAndReceiver is CallTypeAndReceiver.SAFE || isDebuggerContext) {
|
||||||
receiverTypes = receiverTypes?.map { ReceiverType(it.type.makeNotNullable(), it.receiverIndex) }
|
receiverTypes = receiverTypes?.map { ReceiverType(it.type.makeNotNullable(), it.receiverIndex) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (receiverTypes != null && nameExpression.languageVersionSettings.supportsFeature(LanguageFeature.DslMarkersSupport)) {
|
||||||
|
|
||||||
|
val typesByDslScopes = LinkedHashMap<FqName, MutableList<ReceiverType>>()
|
||||||
|
|
||||||
|
receiverTypes
|
||||||
|
.mapNotNull { receiver ->
|
||||||
|
val dslMarkers = receiver.type.extractDslMarkerFqNames()
|
||||||
|
(receiver to dslMarkers).takeIf { dslMarkers.isNotEmpty() }
|
||||||
|
}
|
||||||
|
.forEach { (v, dslMarkers) -> dslMarkers.forEach { typesByDslScopes.getOrPut(it, { mutableListOf() }) += v } }
|
||||||
|
|
||||||
|
val shadowedDslReceivers = mutableSetOf<ReceiverType>()
|
||||||
|
typesByDslScopes.flatMapTo(shadowedDslReceivers) { (_, v) -> v.asSequence().drop(1).asIterable() }
|
||||||
|
|
||||||
|
receiverTypes -= shadowedDslReceivers
|
||||||
|
}
|
||||||
|
|
||||||
return receiverTypes
|
return receiverTypes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-3
@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
|
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||||
import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors
|
import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||||
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -47,6 +48,7 @@ import org.jetbrains.kotlin.types.TypeUtils
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
import org.jetbrains.kotlin.utils.ifEmpty
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
interface AbstractLookupElementFactory {
|
interface AbstractLookupElementFactory {
|
||||||
@@ -347,9 +349,26 @@ class LookupElementFactory(
|
|||||||
receiverTypes: Collection<ReceiverType>,
|
receiverTypes: Collection<ReceiverType>,
|
||||||
onReceiverTypeMismatch: CallableWeight?
|
onReceiverTypeMismatch: CallableWeight?
|
||||||
): CallableWeight? {
|
): CallableWeight? {
|
||||||
val receiverParameter = extensionReceiverParameter
|
|
||||||
?: dispatchReceiverParameter
|
val bothReceivers = listOfNotNull(extensionReceiverParameter, dispatchReceiverParameter)
|
||||||
?: return null
|
|
||||||
|
val receiverTypesForFirstReceiver = receiverTypes.filterNot { it.implicit }.ifEmpty { receiverTypes }
|
||||||
|
|
||||||
|
val weights = bothReceivers.zip(generateSequence(receiverTypesForFirstReceiver) { receiverTypes }.asIterable())
|
||||||
|
.map { (receiverParameter, receiverTypes) ->
|
||||||
|
callableWeightBasedOnReceiver(receiverTypes, onReceiverTypeMismatch, receiverParameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weights.any { it == onReceiverTypeMismatch }) return onReceiverTypeMismatch
|
||||||
|
return weights.firstOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun CallableDescriptor.callableWeightBasedOnReceiver(
|
||||||
|
receiverTypes: Collection<ReceiverType>,
|
||||||
|
onReceiverTypeMismatch: CallableWeight?,
|
||||||
|
receiverParameter: ReceiverParameterDescriptor
|
||||||
|
): CallableWeight? {
|
||||||
|
if ((receiverParameter.value as? TransientReceiver)?.type?.isFunctionType == true) return null
|
||||||
|
|
||||||
val matchingReceiverIndices = HashSet<Int>()
|
val matchingReceiverIndices = HashSet<Int>()
|
||||||
var bestReceiverType: ReceiverType? = null
|
var bestReceiverType: ReceiverType? = null
|
||||||
|
|||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
@DslMarker
|
||||||
|
annotation class SimpleDsl
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslRoot {
|
||||||
|
fun container(body: DslContainer.() -> Unit) {
|
||||||
|
body(DslContainer())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslContainer {
|
||||||
|
fun child(body: DslChild.() -> Unit) {
|
||||||
|
body(DslChild())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun otherChild(body: DslOtherChild.() -> Unit) {
|
||||||
|
body(DslOtherChild())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslChild {
|
||||||
|
operator fun String.unaryMinus() {
|
||||||
|
println(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DslMarker
|
||||||
|
annotation class SimpleOtherDsl
|
||||||
|
|
||||||
|
@SimpleOtherDsl
|
||||||
|
class DslOtherChild {
|
||||||
|
fun otherThing() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dsl(body: DslRoot.() -> Unit) {
|
||||||
|
body(DslRoot())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
dsl {
|
||||||
|
container {
|
||||||
|
child {
|
||||||
|
-"Some"
|
||||||
|
|
||||||
|
}
|
||||||
|
otherChild {
|
||||||
|
otherThing()
|
||||||
|
<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: {"lookupString":"otherThing", "attributes": ["bold"]}
|
||||||
|
// EXIST: {"lookupString":"child", "attributes": ["bold"]}
|
||||||
|
// EXIST: {"lookupString":"otherChild", "attributes": ["bold"]}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
@DslMarker
|
||||||
|
annotation class SimpleDsl
|
||||||
|
|
||||||
|
class DslRoot {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DslContainer
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslContainerOne : DslContainer {
|
||||||
|
fun DslContainer.one() {
|
||||||
|
println(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslContainerTwo : DslContainer {
|
||||||
|
fun DslContainer.two() {
|
||||||
|
println(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DslRoot.containerOne(body: DslContainerOne.() -> Unit) {
|
||||||
|
body(DslContainerOne())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DslRoot.containerTwo(body: DslContainerTwo.() -> Unit) {
|
||||||
|
body(DslContainerTwo())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dsl(body: DslRoot.() -> Unit) {
|
||||||
|
body(DslRoot())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
dsl {
|
||||||
|
containerOne {
|
||||||
|
containerTwo {
|
||||||
|
<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: {"lookupString":"two", "attributes":""}
|
||||||
|
// EXIST: {"lookupString":"one", "attributes":["grayed"]}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
@DslMarker
|
||||||
|
annotation class SimpleDsl
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslRoot {
|
||||||
|
fun container(body: DslContainer.() -> Unit) {
|
||||||
|
body(DslContainer())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslContainer {
|
||||||
|
fun child(body: DslChild.() -> Unit) {
|
||||||
|
body(DslChild())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslChild {
|
||||||
|
operator fun String.unaryMinus() {
|
||||||
|
println(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dsl(body: DslRoot.() -> Unit) {
|
||||||
|
body(DslRoot())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
dsl {
|
||||||
|
container {
|
||||||
|
child {
|
||||||
|
-"Some"
|
||||||
|
<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: {"lookupString":"container", "attributes":["grayed"]}
|
||||||
|
// EXIST: {"lookupString":"child", "attributes":["grayed"]}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
@DslMarker
|
||||||
|
annotation class SimpleDsl
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslRoot {
|
||||||
|
fun container(body: DslContainer.() -> Unit) {
|
||||||
|
body(DslContainer())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslContainer {
|
||||||
|
fun child(body: DslChild.() -> Unit) {
|
||||||
|
body(DslChild())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun otherChild(body: DslOtherChild.() -> Unit) {
|
||||||
|
body(DslOtherChild())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun anotherChild(body: DslAnotherChild.() -> Unit) {
|
||||||
|
body(DslAnotherChild())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslChild {
|
||||||
|
operator fun String.unaryMinus() {
|
||||||
|
println(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DslMarker
|
||||||
|
annotation class SimpleOtherDsl
|
||||||
|
|
||||||
|
@SimpleOtherDsl
|
||||||
|
class DslOtherChild {
|
||||||
|
fun otherThing() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SimpleOtherDsl @SimpleDsl
|
||||||
|
class DslAnotherChild {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dsl(body: DslRoot.() -> Unit) {
|
||||||
|
body(DslRoot())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
dsl {
|
||||||
|
container {
|
||||||
|
child {
|
||||||
|
-"Some"
|
||||||
|
|
||||||
|
}
|
||||||
|
otherChild {
|
||||||
|
otherThing()
|
||||||
|
anotherChild {
|
||||||
|
<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: {lookupString:"otherThing", attributes:["grayed"]}
|
||||||
|
// EXIST: {lookupString:"child", attributes:["grayed"]}
|
||||||
|
// EXIST: {lookupString:"otherChild", attributes:["grayed"]}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
@DslMarker
|
||||||
|
annotation class SimpleDsl
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslRoot {
|
||||||
|
fun container(body: DslContainer.() -> Unit) {
|
||||||
|
body(DslContainer())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslContainer {
|
||||||
|
fun child(body: DslChild.() -> Unit) {
|
||||||
|
body(DslChild())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslChild {
|
||||||
|
operator fun String.unaryMinus() {
|
||||||
|
println(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dsl(body: DslRoot.() -> Unit) {
|
||||||
|
body(DslRoot())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
dsl {
|
||||||
|
container {
|
||||||
|
<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: {"lookupString":"child", "attributes":["bold"]}
|
||||||
|
// EXIST: {"lookupString":"container", "attributes":["grayed"]}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
@DslMarker
|
||||||
|
annotation class SimpleDsl
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslRoot {
|
||||||
|
fun container(body: DslContainer.() -> Unit) {
|
||||||
|
body(DslContainer())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslContainer {
|
||||||
|
fun child(body: DslChild.() -> Unit) {
|
||||||
|
body(DslChild())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SimpleDsl
|
||||||
|
class DslChild {
|
||||||
|
operator fun String.unaryMinus() {
|
||||||
|
println(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dsl(body: DslRoot.() -> Unit) {
|
||||||
|
body(DslRoot())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
dsl {
|
||||||
|
<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: {"lookupString":"container", "attributes":["bold"]}
|
||||||
+45
@@ -1310,6 +1310,51 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/idea-completion/testData/basic/common/dslMarker")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class DslMarker extends AbstractJSBasicCompletionTest {
|
||||||
|
@TestMetadata("2dslsInsideOtherChild.kt")
|
||||||
|
public void test2dslsInsideOtherChild() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/dslMarker/2dslsInsideOtherChild.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("2receivers.kt")
|
||||||
|
public void test2receivers() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/dslMarker/2receivers.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInDslMarker() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/dslMarker"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("child.kt")
|
||||||
|
public void testChild() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/dslMarker/child.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compositeDsl.kt")
|
||||||
|
public void testCompositeDsl() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/dslMarker/compositeDsl.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("container.kt")
|
||||||
|
public void testContainer() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/dslMarker/container.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("root.kt")
|
||||||
|
public void testRoot() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/dslMarker/root.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/basic/common/extensionFunctionTypeValues")
|
@TestMetadata("idea/idea-completion/testData/basic/common/extensionFunctionTypeValues")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+45
@@ -1310,6 +1310,51 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/idea-completion/testData/basic/common/dslMarker")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class DslMarker extends AbstractJvmBasicCompletionTest {
|
||||||
|
@TestMetadata("2dslsInsideOtherChild.kt")
|
||||||
|
public void test2dslsInsideOtherChild() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/dslMarker/2dslsInsideOtherChild.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("2receivers.kt")
|
||||||
|
public void test2receivers() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/dslMarker/2receivers.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInDslMarker() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/dslMarker"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("child.kt")
|
||||||
|
public void testChild() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/dslMarker/child.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compositeDsl.kt")
|
||||||
|
public void testCompositeDsl() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/dslMarker/compositeDsl.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("container.kt")
|
||||||
|
public void testContainer() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/dslMarker/container.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("root.kt")
|
||||||
|
public void testRoot() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/dslMarker/root.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/basic/common/extensionFunctionTypeValues")
|
@TestMetadata("idea/idea-completion/testData/basic/common/extensionFunctionTypeValues")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user