Move ClassifierUsageChecker invocation lower in LazyTopDownAnalyzer
Invoking checkers right after resolution of qualified expressions is too early: DeprecatedClassifierUsageChecker tries to load the annotations of a referenced classifier to report deprecation, and that may result in building light classes for not yet analyzed declarations #KT-13954 Fixed
This commit is contained in:
@@ -17,8 +17,54 @@
|
|||||||
package org.jetbrains.kotlin.resolve
|
package org.jetbrains.kotlin.resolve
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtTreeVisitorVoid
|
||||||
|
|
||||||
interface ClassifierUsageChecker {
|
interface ClassifierUsageChecker {
|
||||||
fun check(targetDescriptor: ClassifierDescriptor, trace: BindingTrace, element: PsiElement)
|
fun check(targetDescriptor: ClassifierDescriptor, trace: BindingTrace, element: PsiElement)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun check(declarations: Collection<PsiElement>, trace: BindingTrace, checkers: Iterable<ClassifierUsageChecker>) {
|
||||||
|
val visitor = object : KtTreeVisitorVoid() {
|
||||||
|
override fun visitReferenceExpression(expression: KtReferenceExpression) {
|
||||||
|
super.visitReferenceExpression(expression)
|
||||||
|
|
||||||
|
if (expression is KtNameReferenceExpression && expression.getReferencedNameElementType() == KtTokens.SUPER_KEYWORD) {
|
||||||
|
// Do not run checkers here because super expressions is not a proper expression. For example,
|
||||||
|
// it doesn't make sense to report deprecation on "super" in "super.foo()" if the super class is deprecated.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val target = trace.bindingContext.get(BindingContext.REFERENCE_TARGET, expression) as? ClassifierDescriptor ?: return
|
||||||
|
|
||||||
|
for (checker in checkers) {
|
||||||
|
checker.check(target, trace, expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReferenceToCompanionViaOuterClass(expression, target)) {
|
||||||
|
val outerClass = target.containingDeclaration as ClassDescriptor
|
||||||
|
for (checker in checkers) {
|
||||||
|
checker.check(outerClass, trace, expression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true iff [expression] references the companion of a class Foo via the name Foo, e.g. in `Foo.bar()`
|
||||||
|
*/
|
||||||
|
private fun isReferenceToCompanionViaOuterClass(expression: KtReferenceExpression, target: ClassifierDescriptor?): Boolean {
|
||||||
|
return DescriptorUtils.isCompanionObject(target) &&
|
||||||
|
trace.bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, expression] != null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (declaration in declarations) {
|
||||||
|
declaration.accept(visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ class LazyTopDownAnalyzer(
|
|||||||
private val declarationScopeProvider: DeclarationScopeProvider,
|
private val declarationScopeProvider: DeclarationScopeProvider,
|
||||||
private val qualifiedExpressionResolver: QualifiedExpressionResolver,
|
private val qualifiedExpressionResolver: QualifiedExpressionResolver,
|
||||||
private val identifierChecker: IdentifierChecker,
|
private val identifierChecker: IdentifierChecker,
|
||||||
private val languageVersionSettings: LanguageVersionSettings
|
private val languageVersionSettings: LanguageVersionSettings,
|
||||||
|
private val classifierUsageCheckers: Iterable<ClassifierUsageChecker>
|
||||||
) {
|
) {
|
||||||
fun analyzeDeclarations(topDownAnalysisMode: TopDownAnalysisMode, declarations: Collection<PsiElement>, outerDataFlowInfo: DataFlowInfo): TopDownAnalysisContext {
|
fun analyzeDeclarations(topDownAnalysisMode: TopDownAnalysisMode, declarations: Collection<PsiElement>, outerDataFlowInfo: DataFlowInfo): TopDownAnalysisContext {
|
||||||
|
|
||||||
@@ -204,6 +205,8 @@ class LazyTopDownAnalyzer(
|
|||||||
|
|
||||||
bodyResolver.resolveBodies(c)
|
bodyResolver.resolveBodies(c)
|
||||||
|
|
||||||
|
ClassifierUsageChecker.check(declarations, trace, classifierUsageCheckers)
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-14
@@ -25,12 +25,9 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
|||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
||||||
|
|
||||||
fun resolveQualifierAsReceiverInExpression(
|
fun resolveQualifierAsReceiverInExpression(
|
||||||
qualifier: Qualifier,
|
qualifier: Qualifier, selector: DeclarationDescriptor?, context: ExpressionTypingContext
|
||||||
selector: DeclarationDescriptor?,
|
|
||||||
context: ExpressionTypingContext,
|
|
||||||
classifierUsageCheckers: Iterable<ClassifierUsageChecker>
|
|
||||||
): DeclarationDescriptor {
|
): DeclarationDescriptor {
|
||||||
val referenceTarget = resolveQualifierReferenceTarget(qualifier, selector, context, classifierUsageCheckers)
|
val referenceTarget = resolveQualifierReferenceTarget(qualifier, selector, context)
|
||||||
|
|
||||||
if (referenceTarget is TypeParameterDescriptor) {
|
if (referenceTarget is TypeParameterDescriptor) {
|
||||||
context.trace.report(Errors.TYPE_PARAMETER_ON_LHS_OF_DOT.on(qualifier.referenceExpression, referenceTarget))
|
context.trace.report(Errors.TYPE_PARAMETER_ON_LHS_OF_DOT.on(qualifier.referenceExpression, referenceTarget))
|
||||||
@@ -40,11 +37,9 @@ fun resolveQualifierAsReceiverInExpression(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun resolveQualifierAsStandaloneExpression(
|
fun resolveQualifierAsStandaloneExpression(
|
||||||
qualifier: Qualifier,
|
qualifier: Qualifier, context: ExpressionTypingContext
|
||||||
context: ExpressionTypingContext,
|
|
||||||
classifierUsageCheckers: Iterable<ClassifierUsageChecker>
|
|
||||||
): DeclarationDescriptor {
|
): DeclarationDescriptor {
|
||||||
val referenceTarget = resolveQualifierReferenceTarget(qualifier, null, context, classifierUsageCheckers)
|
val referenceTarget = resolveQualifierReferenceTarget(qualifier, null, context)
|
||||||
|
|
||||||
when (referenceTarget) {
|
when (referenceTarget) {
|
||||||
is TypeAliasDescriptor -> {
|
is TypeAliasDescriptor -> {
|
||||||
@@ -73,8 +68,7 @@ fun resolveQualifierAsStandaloneExpression(
|
|||||||
private fun resolveQualifierReferenceTarget(
|
private fun resolveQualifierReferenceTarget(
|
||||||
qualifier: Qualifier,
|
qualifier: Qualifier,
|
||||||
selector: DeclarationDescriptor?,
|
selector: DeclarationDescriptor?,
|
||||||
context: ExpressionTypingContext,
|
context: ExpressionTypingContext
|
||||||
classifierUsageCheckers: Iterable<ClassifierUsageChecker>
|
|
||||||
): DeclarationDescriptor {
|
): DeclarationDescriptor {
|
||||||
if (qualifier is TypeParameterQualifier) {
|
if (qualifier is TypeParameterQualifier) {
|
||||||
return qualifier.descriptor
|
return qualifier.descriptor
|
||||||
@@ -110,9 +104,6 @@ private fun resolveQualifierReferenceTarget(
|
|||||||
context.trace.recordType(qualifier.expression, classValueTypeDescriptor.defaultType)
|
context.trace.recordType(qualifier.expression, classValueTypeDescriptor.defaultType)
|
||||||
if (classifier.hasCompanionObject) {
|
if (classifier.hasCompanionObject) {
|
||||||
context.trace.record(BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, qualifier.referenceExpression, classifier)
|
context.trace.record(BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, qualifier.referenceExpression, classifier)
|
||||||
for (checker in classifierUsageCheckers) {
|
|
||||||
checker.check(classValueDescriptor, context.trace, qualifier.referenceExpression)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return classValueTypeDescriptor
|
return classValueTypeDescriptor
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import org.jetbrains.kotlin.types.expressions.isWithoutValueArguments
|
|||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
|
|
||||||
class QualifiedExpressionResolver(val classifierUsageCheckers: Iterable<ClassifierUsageChecker>) {
|
class QualifiedExpressionResolver {
|
||||||
fun resolvePackageHeader(
|
fun resolvePackageHeader(
|
||||||
packageDirective: KtPackageDirective,
|
packageDirective: KtPackageDirective,
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
@@ -376,9 +376,7 @@ class QualifiedExpressionResolver(val classifierUsageCheckers: Iterable<Classifi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val classifierDescriptor = scopeForFirstPart?.let {
|
val classifierDescriptor = scopeForFirstPart?.findClassifier(firstPart.name, firstPart.location)
|
||||||
it.findClassifier(firstPart.name, firstPart.location)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (classifierDescriptor != null) {
|
if (classifierDescriptor != null) {
|
||||||
storeResult(trace, firstPart.expression, classifierDescriptor, shouldBeVisibleFrom, position)
|
storeResult(trace, firstPart.expression, classifierDescriptor, shouldBeVisibleFrom, position)
|
||||||
@@ -626,12 +624,6 @@ class QualifiedExpressionResolver(val classifierUsageCheckers: Iterable<Classifi
|
|||||||
|
|
||||||
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptor)
|
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptor)
|
||||||
|
|
||||||
if (descriptor is ClassifierDescriptor) {
|
|
||||||
for (checker in classifierUsageCheckers) {
|
|
||||||
checker.check(descriptor, trace, referenceExpression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descriptor is DeclarationDescriptorWithVisibility) {
|
if (descriptor is DeclarationDescriptorWithVisibility) {
|
||||||
val fromToCheck =
|
val fromToCheck =
|
||||||
if (shouldBeVisibleFrom is PackageFragmentDescriptor && shouldBeVisibleFrom.source == SourceElement.NO_SOURCE && referenceExpression.containingFile !is DummyHolder) {
|
if (shouldBeVisibleFrom is PackageFragmentDescriptor && shouldBeVisibleFrom.source == SourceElement.NO_SOURCE && referenceExpression.containingFile !is DummyHolder) {
|
||||||
|
|||||||
@@ -70,8 +70,7 @@ class CallExpressionResolver(
|
|||||||
private val argumentTypeResolver: ArgumentTypeResolver,
|
private val argumentTypeResolver: ArgumentTypeResolver,
|
||||||
private val dataFlowAnalyzer: DataFlowAnalyzer,
|
private val dataFlowAnalyzer: DataFlowAnalyzer,
|
||||||
private val builtIns: KotlinBuiltIns,
|
private val builtIns: KotlinBuiltIns,
|
||||||
private val qualifiedExpressionResolver: QualifiedExpressionResolver,
|
private val qualifiedExpressionResolver: QualifiedExpressionResolver
|
||||||
private val classifierUsageCheckers: Iterable<ClassifierUsageChecker>
|
|
||||||
) {
|
) {
|
||||||
private lateinit var expressionTypingServices: ExpressionTypingServices
|
private lateinit var expressionTypingServices: ExpressionTypingServices
|
||||||
|
|
||||||
@@ -162,7 +161,7 @@ class CallExpressionResolver(
|
|||||||
val temporaryForQualifier = TemporaryTraceAndCache.create(context, "trace to resolve as qualifier", nameExpression)
|
val temporaryForQualifier = TemporaryTraceAndCache.create(context, "trace to resolve as qualifier", nameExpression)
|
||||||
val contextForQualifier = context.replaceTraceAndCache(temporaryForQualifier)
|
val contextForQualifier = context.replaceTraceAndCache(temporaryForQualifier)
|
||||||
qualifiedExpressionResolver.resolveNameExpressionAsQualifierForDiagnostics(nameExpression, receiver, contextForQualifier)?.let {
|
qualifiedExpressionResolver.resolveNameExpressionAsQualifierForDiagnostics(nameExpression, receiver, contextForQualifier)?.let {
|
||||||
resolveQualifierAsStandaloneExpression(it, contextForQualifier, classifierUsageCheckers)
|
resolveQualifierAsStandaloneExpression(it, contextForQualifier)
|
||||||
temporaryForQualifier.commit()
|
temporaryForQualifier.commit()
|
||||||
} ?: temporaryForVariable.commit()
|
} ?: temporaryForVariable.commit()
|
||||||
return noTypeInfo(context)
|
return noTypeInfo(context)
|
||||||
@@ -225,7 +224,7 @@ class CallExpressionResolver(
|
|||||||
val type = functionDescriptor.returnType
|
val type = functionDescriptor.returnType
|
||||||
// Extracting jump out possible and jump point flow info from arguments, if any
|
// Extracting jump out possible and jump point flow info from arguments, if any
|
||||||
val arguments = callExpression.valueArguments
|
val arguments = callExpression.valueArguments
|
||||||
val resultFlowInfo = resolvedCall!!.dataFlowInfoForArguments.resultInfo
|
val resultFlowInfo = resolvedCall.dataFlowInfoForArguments.resultInfo
|
||||||
var jumpFlowInfo = resultFlowInfo
|
var jumpFlowInfo = resultFlowInfo
|
||||||
var jumpOutPossible = false
|
var jumpOutPossible = false
|
||||||
for (argument in arguments) {
|
for (argument in arguments) {
|
||||||
@@ -449,7 +448,7 @@ class CallExpressionResolver(
|
|||||||
context.trace.get(BindingContext.REFERENCE_TARGET, it)
|
context.trace.get(BindingContext.REFERENCE_TARGET, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveQualifierAsReceiverInExpression(qualifier, selectorDescriptor, context, classifierUsageCheckers)
|
resolveQualifierAsReceiverInExpression(qualifier, selectorDescriptor, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+4
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.psi.KtReferenceExpression
|
|||||||
import org.jetbrains.kotlin.psi.KtUnaryExpression
|
import org.jetbrains.kotlin.psi.KtUnaryExpression
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||||
import org.jetbrains.kotlin.resolve.createDeprecationDiagnostic
|
import org.jetbrains.kotlin.resolve.createDeprecationDiagnostic
|
||||||
import org.jetbrains.kotlin.resolve.getDeprecation
|
import org.jetbrains.kotlin.resolve.getDeprecation
|
||||||
|
|
||||||
@@ -38,6 +39,9 @@ object DeprecatedCallChecker : CallChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun check(targetDescriptor: CallableDescriptor, trace: BindingTrace, element: PsiElement) {
|
private fun check(targetDescriptor: CallableDescriptor, trace: BindingTrace, element: PsiElement) {
|
||||||
|
// Objects will be checked by DeprecatedClassifierUsageChecker
|
||||||
|
if (targetDescriptor is FakeCallableDescriptorForObject) return
|
||||||
|
|
||||||
val deprecation = targetDescriptor.getDeprecation()
|
val deprecation = targetDescriptor.getDeprecation()
|
||||||
|
|
||||||
// avoid duplicating diagnostic when deprecation for property effectively deprecates setter
|
// avoid duplicating diagnostic when deprecation for property effectively deprecates setter
|
||||||
|
|||||||
@@ -18,3 +18,15 @@ fun useCompanion() {
|
|||||||
Another.<!DEPRECATION!>Companion<!>.use()
|
Another.<!DEPRECATION!>Companion<!>.use()
|
||||||
<!DEPRECATION!>Another<!>.use()
|
<!DEPRECATION!>Another<!>.use()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Some")
|
||||||
|
class Some {
|
||||||
|
companion object {
|
||||||
|
fun use() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun some() {
|
||||||
|
<!DEPRECATION!>Some<!>.use()
|
||||||
|
<!DEPRECATION!>Some<!>.Companion.use()
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
public fun first(): kotlin.Unit
|
public fun first(): kotlin.Unit
|
||||||
|
public fun some(): kotlin.Unit
|
||||||
public fun useCompanion(): kotlin.Unit
|
public fun useCompanion(): kotlin.Unit
|
||||||
|
|
||||||
public final class Another {
|
public final class Another {
|
||||||
@@ -18,3 +19,18 @@ public final class Another {
|
|||||||
public final fun use(): kotlin.Unit
|
public final fun use(): kotlin.Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@kotlin.Deprecated(message = "Some") public final class Some {
|
||||||
|
public constructor Some()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
public companion object Companion {
|
||||||
|
private constructor Companion()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
public final fun use(): kotlin.Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// FILE: foo/A.kt
|
||||||
|
|
||||||
|
package foo
|
||||||
|
|
||||||
|
class A(val c: C)
|
||||||
|
|
||||||
|
// FILE: foo/B.kt
|
||||||
|
|
||||||
|
package foo
|
||||||
|
|
||||||
|
class B {
|
||||||
|
interface D {
|
||||||
|
fun foo(): E
|
||||||
|
}
|
||||||
|
|
||||||
|
class E
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: foo/C.java
|
||||||
|
|
||||||
|
package foo;
|
||||||
|
|
||||||
|
import static foo.B.D.*;
|
||||||
|
|
||||||
|
@SuppressWarnings("RedundantTypeArguments")
|
||||||
|
public class C {}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
package foo {
|
||||||
|
|
||||||
|
public final class A {
|
||||||
|
public constructor A(/*0*/ c: foo.C)
|
||||||
|
public final val c: foo.C
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class B {
|
||||||
|
public constructor B()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
public interface D {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract fun foo(): foo.B.E
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class E {
|
||||||
|
public constructor E()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.SuppressWarnings(value = "RedundantTypeArguments") public open class C {
|
||||||
|
public constructor C()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14826,6 +14826,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt13954.kt")
|
||||||
|
public void testKt13954() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/regressions/kt13954.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt1489_1728.kt")
|
@TestMetadata("kt1489_1728.kt")
|
||||||
public void testKt1489_1728() throws Exception {
|
public void testKt1489_1728() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/regressions/kt1489_1728.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/regressions/kt1489_1728.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user