[FIR] add tests on external annotations
Tests are excluded in COMPILED_JAVA mode because in this mode external annotations are not present at all ^KT-62310
This commit is contained in:
committed by
Space Team
parent
e452113a7a
commit
2cac922cd0
+12
@@ -136,6 +136,18 @@ public class Fe10IdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated ext
|
||||
runTest("analysis/analysis-api/testData/symbols/symbolByReference/javaMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaMethodWithExternalNotNullAnnotation.kt")
|
||||
public void testJavaMethodWithExternalNotNullAnnotation() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/symbols/symbolByReference/javaMethodWithExternalNotNullAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaMethodWithNotNullAnnotation.kt")
|
||||
public void testJavaMethodWithNotNullAnnotation() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/symbols/symbolByReference/javaMethodWithNotNullAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaStaticField.kt")
|
||||
public void testJavaStaticField() throws Exception {
|
||||
|
||||
+12
@@ -136,6 +136,18 @@ public class FirIdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated exte
|
||||
runTest("analysis/analysis-api/testData/symbols/symbolByReference/javaMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaMethodWithExternalNotNullAnnotation.kt")
|
||||
public void testJavaMethodWithExternalNotNullAnnotation() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/symbols/symbolByReference/javaMethodWithExternalNotNullAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaMethodWithNotNullAnnotation.kt")
|
||||
public void testJavaMethodWithNotNullAnnotation() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/symbols/symbolByReference/javaMethodWithNotNullAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaStaticField.kt")
|
||||
public void testJavaStaticField() throws Exception {
|
||||
|
||||
+12
@@ -136,6 +136,18 @@ public class FirStandaloneNormalAnalysisSourceModuleSymbolByReferenceTestGenerat
|
||||
runTest("analysis/analysis-api/testData/symbols/symbolByReference/javaMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaMethodWithExternalNotNullAnnotation.kt")
|
||||
public void testJavaMethodWithExternalNotNullAnnotation() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/symbols/symbolByReference/javaMethodWithExternalNotNullAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaMethodWithNotNullAnnotation.kt")
|
||||
public void testJavaMethodWithNotNullAnnotation() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/symbols/symbolByReference/javaMethodWithNotNullAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaStaticField.kt")
|
||||
public void testJavaStaticField() throws Exception {
|
||||
|
||||
+6
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -16,10 +16,12 @@ import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisA
|
||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestServiceRegistrar
|
||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.preprocessors.ExternalAnnotationsSourcePreprocessor
|
||||
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.configuration.ExternalAnnotationsEnvironmentConfigurator
|
||||
|
||||
public object StandaloneModeConfigurator : AnalysisApiTestConfigurator() {
|
||||
object StandaloneModeConfigurator : AnalysisApiTestConfigurator() {
|
||||
override val analyseInDependentSession: Boolean get() = false
|
||||
override val frontendKind: FrontendKind get() = FrontendKind.Fir
|
||||
|
||||
@@ -31,6 +33,8 @@ public object StandaloneModeConfigurator : AnalysisApiTestConfigurator() {
|
||||
useAdditionalService<KtModuleFactory> { KtSourceModuleFactory() }
|
||||
useDirectives(SealedClassesInheritorsCaclulatorPreAnalysisHandler.Directives)
|
||||
usePreAnalysisHandlers(::SealedClassesInheritorsCaclulatorPreAnalysisHandler)
|
||||
useConfigurators(::ExternalAnnotationsEnvironmentConfigurator)
|
||||
useSourcePreprocessor(::ExternalAnnotationsSourcePreprocessor)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
open fun foo(): kotlin.String!
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
KtFunctionSymbol:
|
||||
annotationsList: []
|
||||
callableIdIfNonLocal: /JavaClass.foo
|
||||
contextReceivers: []
|
||||
contractEffects: []
|
||||
hasStableParameterNames: false
|
||||
isActual: false
|
||||
isBuiltinFunctionInvoke: false
|
||||
isExpect: false
|
||||
isExtension: false
|
||||
isExternal: false
|
||||
isInfix: false
|
||||
isInline: false
|
||||
isOperator: false
|
||||
isOverride: false
|
||||
isStatic: false
|
||||
isSuspend: false
|
||||
modality: OPEN
|
||||
name: foo
|
||||
origin: JAVA
|
||||
receiverParameter: null
|
||||
returnType: KtFlexibleType:
|
||||
annotationsList: []
|
||||
type: kotlin/String!
|
||||
symbolKind: CLASS_MEMBER
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: Public
|
||||
getDispatchReceiver(): KtUsualClassType:
|
||||
annotationsList: []
|
||||
ownTypeArguments: []
|
||||
type: JavaClass
|
||||
getContainingModule: KtSourceModule "Sources of main"
|
||||
deprecationStatus: null
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
// FILE: main.kt
|
||||
fun some() {
|
||||
JavaClass().f<caret>oo();
|
||||
}
|
||||
// FILE: JavaClass.java
|
||||
public class JavaClass {
|
||||
public String foo() {};
|
||||
}
|
||||
// FILE: annotations.xml
|
||||
<root>
|
||||
<item name='JavaClass java.lang.String foo()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
+1
@@ -0,0 +1 @@
|
||||
open fun foo(): kotlin.String
|
||||
analysis/analysis-api/testData/symbols/symbolByReference/javaMethodWithExternalNotNullAnnotation.txt
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
KtFunctionSymbol:
|
||||
annotationsList: [
|
||||
org/jetbrains/annotations/NotNull()
|
||||
psi: null
|
||||
]
|
||||
callableIdIfNonLocal: /JavaClass.foo
|
||||
contextReceivers: []
|
||||
contractEffects: []
|
||||
hasStableParameterNames: false
|
||||
isActual: false
|
||||
isBuiltinFunctionInvoke: false
|
||||
isExpect: false
|
||||
isExtension: false
|
||||
isExternal: false
|
||||
isInfix: false
|
||||
isInline: false
|
||||
isOperator: false
|
||||
isOverride: false
|
||||
isStatic: false
|
||||
isSuspend: false
|
||||
modality: OPEN
|
||||
name: foo
|
||||
origin: JAVA
|
||||
receiverParameter: null
|
||||
returnType: KtUsualClassType:
|
||||
annotationsList: []
|
||||
ownTypeArguments: []
|
||||
type: @EnhancedNullability kotlin/String
|
||||
symbolKind: CLASS_MEMBER
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: Public
|
||||
getDispatchReceiver(): KtUsualClassType:
|
||||
annotationsList: []
|
||||
ownTypeArguments: []
|
||||
type: JavaClass
|
||||
getContainingModule: KtSourceModule "Sources of main"
|
||||
deprecationStatus: null
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
KtFunctionSymbol:
|
||||
annotationsList: [
|
||||
org/jetbrains/annotations/NotNull()
|
||||
psi: null
|
||||
]
|
||||
callableIdIfNonLocal: /JavaClass.foo
|
||||
contextReceivers: []
|
||||
contractEffects: []
|
||||
hasStableParameterNames: false
|
||||
isActual: false
|
||||
isBuiltinFunctionInvoke: false
|
||||
isExpect: false
|
||||
isExtension: false
|
||||
isExternal: false
|
||||
isInfix: false
|
||||
isInline: false
|
||||
isOperator: false
|
||||
isOverride: false
|
||||
isStatic: false
|
||||
isSuspend: false
|
||||
modality: OPEN
|
||||
name: foo
|
||||
origin: JAVA
|
||||
receiverParameter: null
|
||||
returnType: KtUsualClassType:
|
||||
annotationsList: []
|
||||
ownTypeArguments: []
|
||||
type: kotlin/String
|
||||
symbolKind: CLASS_MEMBER
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: Public
|
||||
getDispatchReceiver(): KtUsualClassType:
|
||||
annotationsList: []
|
||||
ownTypeArguments: []
|
||||
type: JavaClass
|
||||
getContainingModule: KtSourceModule "Sources of main"
|
||||
deprecationStatus: null
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
// FILE: main.kt
|
||||
fun some() {
|
||||
JavaClass().f<caret>oo();
|
||||
}
|
||||
// FILE: JavaClass.java
|
||||
import import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class JavaClass {
|
||||
@NotNull
|
||||
public String foo() {};
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
open fun foo(): kotlin.String
|
||||
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
KtFunctionSymbol:
|
||||
annotationsList: [
|
||||
org/jetbrains/annotations/NotNull()
|
||||
psi: null
|
||||
]
|
||||
callableIdIfNonLocal: /JavaClass.foo
|
||||
contextReceivers: []
|
||||
contractEffects: []
|
||||
hasStableParameterNames: false
|
||||
isActual: false
|
||||
isBuiltinFunctionInvoke: false
|
||||
isExpect: false
|
||||
isExtension: false
|
||||
isExternal: false
|
||||
isInfix: false
|
||||
isInline: false
|
||||
isOperator: false
|
||||
isOverride: false
|
||||
isStatic: false
|
||||
isSuspend: false
|
||||
modality: OPEN
|
||||
name: foo
|
||||
origin: JAVA
|
||||
receiverParameter: null
|
||||
returnType: KtUsualClassType:
|
||||
annotationsList: []
|
||||
ownTypeArguments: []
|
||||
type: @EnhancedNullability kotlin/String
|
||||
symbolKind: CLASS_MEMBER
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: Public
|
||||
getDispatchReceiver(): KtUsualClassType:
|
||||
annotationsList: []
|
||||
ownTypeArguments: []
|
||||
type: JavaClass
|
||||
getContainingModule: KtSourceModule "Sources of main"
|
||||
deprecationStatus: null
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -183,7 +183,7 @@ object TestModuleStructureFactory {
|
||||
fun createSourcePsiFiles(
|
||||
testModule: TestModule,
|
||||
testServices: TestServices,
|
||||
project: Project
|
||||
project: Project,
|
||||
): List<PsiFile> {
|
||||
return testModule.files.map { testFile ->
|
||||
when {
|
||||
@@ -192,7 +192,7 @@ object TestModuleStructureFactory {
|
||||
KtTestUtil.createFile(testFile.name, fileText, project)
|
||||
}
|
||||
|
||||
testFile.isJavaFile -> {
|
||||
testFile.isJavaFile || testFile.isExternalAnnotation -> {
|
||||
val filePath = testServices.sourceFileProvider.getRealFileForSourceFile(testFile)
|
||||
val virtualFile =
|
||||
testServices.environmentManager.getApplicationEnvironment().localFileSystem.findFileByIoFile(filePath)
|
||||
@@ -205,7 +205,5 @@ object TestModuleStructureFactory {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
// SKIP_WHEN_OUT_OF_CONTENT_ROOT
|
||||
// FILE: usage.kt
|
||||
<expr>
|
||||
fun test() = ClassWithExternalAnnotatedMembers().externalNotNullMethod()
|
||||
</expr>
|
||||
|
||||
// FILE: ClassWithExternalAnnotatedMembers.java
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
public String externalNotNullMethod() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: annotations.xml
|
||||
<root>
|
||||
<item name='ClassWithExternalAnnotatedMembers java.lang.String externalNotNullMethod()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
KT element: KtNamedFunction
|
||||
FIR element: FirSimpleFunctionImpl
|
||||
FIR source kind: KtRealSourceElementKind
|
||||
|
||||
FIR element rendered:
|
||||
public final [ResolvedTo(BODY_RESOLVE)] fun test(): R|kotlin/String| {
|
||||
^test R|/ClassWithExternalAnnotatedMembers.ClassWithExternalAnnotatedMembers|().R|/ClassWithExternalAnnotatedMembers.externalNotNullMethod|()
|
||||
}
|
||||
|
||||
FIR FILE:
|
||||
FILE: [ResolvedTo(IMPORTS)] usage.kt
|
||||
public final [ResolvedTo(BODY_RESOLVE)] fun test(): R|kotlin/String| {
|
||||
^test R|/ClassWithExternalAnnotatedMembers.ClassWithExternalAnnotatedMembers|().R|/ClassWithExternalAnnotatedMembers.externalNotNullMethod|()
|
||||
}
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
// SKIP_WHEN_OUT_OF_CONTENT_ROOT
|
||||
// FILE: usage.kt
|
||||
<expr>
|
||||
fun test() = ClassWithExternalAnnotatedMembers().notNullMethod()
|
||||
</expr>
|
||||
|
||||
// FILE: ClassWithExternalAnnotatedMembers.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
@NotNull
|
||||
public String notNullMethod() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
KT element: KtNamedFunction
|
||||
FIR element: FirSimpleFunctionImpl
|
||||
FIR source kind: KtRealSourceElementKind
|
||||
|
||||
FIR element rendered:
|
||||
public final [ResolvedTo(BODY_RESOLVE)] fun test(): R|kotlin/String| {
|
||||
^test R|/ClassWithExternalAnnotatedMembers.ClassWithExternalAnnotatedMembers|().R|/ClassWithExternalAnnotatedMembers.notNullMethod|()
|
||||
}
|
||||
|
||||
FIR FILE:
|
||||
FILE: [ResolvedTo(IMPORTS)] usage.kt
|
||||
public final [ResolvedTo(BODY_RESOLVE)] fun test(): R|kotlin/String| {
|
||||
^test R|/ClassWithExternalAnnotatedMembers.ClassWithExternalAnnotatedMembers|().R|/ClassWithExternalAnnotatedMembers.notNullMethod|()
|
||||
}
|
||||
+12
@@ -1163,6 +1163,12 @@ public class OutOfContentRootGetOrBuildFirTestGenerated extends AbstractOutOfCon
|
||||
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/wholeDeclaration/enumEntry.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("externalJavaAnnotation.kt")
|
||||
public void testExternalJavaAnnotation() throws Exception {
|
||||
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/wholeDeclaration/externalJavaAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionTypeParemeter.kt")
|
||||
public void testFunctionTypeParemeter() throws Exception {
|
||||
@@ -1223,6 +1229,12 @@ public class OutOfContentRootGetOrBuildFirTestGenerated extends AbstractOutOfCon
|
||||
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/wholeDeclaration/nestedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("notNullJavaAnnotation.kt")
|
||||
public void testNotNullJavaAnnotation() throws Exception {
|
||||
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/wholeDeclaration/notNullJavaAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("primaryConstructorValValueParameter.kt")
|
||||
public void testPrimaryConstructorValValueParameter() throws Exception {
|
||||
|
||||
+12
@@ -1163,6 +1163,12 @@ public class SourceGetOrBuildFirTestGenerated extends AbstractSourceGetOrBuildFi
|
||||
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/wholeDeclaration/enumEntry.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("externalJavaAnnotation.kt")
|
||||
public void testExternalJavaAnnotation() throws Exception {
|
||||
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/wholeDeclaration/externalJavaAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionTypeParemeter.kt")
|
||||
public void testFunctionTypeParemeter() throws Exception {
|
||||
@@ -1223,6 +1229,12 @@ public class SourceGetOrBuildFirTestGenerated extends AbstractSourceGetOrBuildFi
|
||||
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/wholeDeclaration/nestedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("notNullJavaAnnotation.kt")
|
||||
public void testNotNullJavaAnnotation() throws Exception {
|
||||
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/wholeDeclaration/notNullJavaAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("primaryConstructorValValueParameter.kt")
|
||||
public void testPrimaryConstructorValValueParameter() throws Exception {
|
||||
|
||||
+5
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -18,8 +18,10 @@ import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisA
|
||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestServiceRegistrar
|
||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.preprocessors.ExternalAnnotationsSourcePreprocessor
|
||||
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.configuration.ExternalAnnotationsEnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator
|
||||
|
||||
abstract class AnalysisApiFirSourceLikeTestConfigurator(override val analyseInDependentSession: Boolean) : AnalysisApiTestConfigurator() {
|
||||
@@ -30,7 +32,8 @@ abstract class AnalysisApiFirSourceLikeTestConfigurator(override val analyseInDe
|
||||
useDirectives(SealedClassesInheritorsCaclulatorPreAnalysisHandler.Directives)
|
||||
usePreAnalysisHandlers(::SealedClassesInheritorsCaclulatorPreAnalysisHandler)
|
||||
configureOptionalTestCompilerPlugin()
|
||||
useConfigurators(::JvmEnvironmentConfigurator)
|
||||
useConfigurators(::JvmEnvironmentConfigurator, ::ExternalAnnotationsEnvironmentConfigurator)
|
||||
useSourcePreprocessor(::ExternalAnnotationsSourcePreprocessor)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ public class FirPsiOldFrontendForeignAnnotationsCompiledJavaTestGenerated extend
|
||||
public class Tests {
|
||||
@Test
|
||||
public void testAllFilesPresentInTests() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "externalAnnotations");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+58
@@ -146,6 +146,64 @@ public class FirPsiOldFrontendForeignAnnotationsCompiledJavaWithPsiClassReadingT
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/rxjava3Warnings.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ExternalAnnotations {
|
||||
@Test
|
||||
public void testAllFilesPresentInExternalAnnotations() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorParameterNotNull.kt")
|
||||
public void testConstructorParameterNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/constructorParameterNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorParameterNotNull2.kt")
|
||||
public void testConstructorParameterNotNull2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/constructorParameterNotNull2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fieldNotNull.kt")
|
||||
public void testFieldNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/fieldNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fieldNotNullAnnotationWithPackage.kt")
|
||||
public void testFieldNotNullAnnotationWithPackage() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/fieldNotNullAnnotationWithPackage.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodNotNull.kt")
|
||||
public void testMethodNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodNotNullFromAnotherModule.kt")
|
||||
public void testMethodNotNullFromAnotherModule() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodNotNullFromAnotherModule.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodParameterNotNull.kt")
|
||||
public void testMethodParameterNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodParameterNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodParameterNotNull2.kt")
|
||||
public void testMethodParameterNotNull2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodParameterNotNull2.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/foreignAnnotationsTests/tests/jsr305")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+58
@@ -146,6 +146,64 @@ public class FirPsiOldFrontendForeignAnnotationsSourceJavaTestGenerated extends
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/rxjava3Warnings.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ExternalAnnotations {
|
||||
@Test
|
||||
public void testAllFilesPresentInExternalAnnotations() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorParameterNotNull.kt")
|
||||
public void testConstructorParameterNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/constructorParameterNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorParameterNotNull2.kt")
|
||||
public void testConstructorParameterNotNull2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/constructorParameterNotNull2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fieldNotNull.kt")
|
||||
public void testFieldNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/fieldNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fieldNotNullAnnotationWithPackage.kt")
|
||||
public void testFieldNotNullAnnotationWithPackage() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/fieldNotNullAnnotationWithPackage.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodNotNull.kt")
|
||||
public void testMethodNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodNotNullFromAnotherModule.kt")
|
||||
public void testMethodNotNullFromAnotherModule() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodNotNullFromAnotherModule.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodParameterNotNull.kt")
|
||||
public void testMethodParameterNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodParameterNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodParameterNotNull2.kt")
|
||||
public void testMethodParameterNotNull2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodParameterNotNull2.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/foreignAnnotationsTests/tests/jsr305")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+5
-1
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.test.services
|
||||
|
||||
import com.intellij.codeInsight.ExternalAnnotationsManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.psi.PsiManager
|
||||
@@ -139,6 +140,9 @@ val TestFile.isMjsFile: Boolean
|
||||
val TestModule.javaFiles: List<TestFile>
|
||||
get() = files.filter { it.isJavaFile }
|
||||
|
||||
val TestFile.isExternalAnnotation: Boolean
|
||||
get() = name == ExternalAnnotationsManager.ANNOTATIONS_XML
|
||||
|
||||
fun SourceFileProvider.getRealJavaFiles(module: TestModule): List<File> {
|
||||
return module.javaFiles.map { getRealFileForSourceFile(it) }
|
||||
}
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// FILE: ClassWithExternalAnnotatedMembers.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
public ClassWithExternalAnnotatedMembers(Integer i) { // with external annotation on parameter
|
||||
|
||||
}
|
||||
|
||||
public ClassWithExternalAnnotatedMembers(@NotNull String s) {
|
||||
|
||||
}
|
||||
|
||||
public ClassWithExternalAnnotatedMembers(Boolean b) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: usage.kt
|
||||
fun test() {
|
||||
val i: Int? = null
|
||||
<!NONE_APPLICABLE!>ClassWithExternalAnnotatedMembers<!>(i)
|
||||
|
||||
val s: String? = null
|
||||
<!NONE_APPLICABLE!>ClassWithExternalAnnotatedMembers<!>(s)
|
||||
|
||||
val b: Boolean? = null
|
||||
ClassWithExternalAnnotatedMembers(b)
|
||||
|
||||
ClassWithExternalAnnotatedMembers(null)
|
||||
}
|
||||
|
||||
// FILE: annotations.xml
|
||||
<root>
|
||||
<item name='ClassWithExternalAnnotatedMembers ClassWithExternalAnnotatedMembers(java.lang.Integer) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// FILE: ClassWithExternalAnnotatedMembers.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
public ClassWithExternalAnnotatedMembers(Integer i) { // with external annotation on parameter
|
||||
|
||||
}
|
||||
|
||||
public ClassWithExternalAnnotatedMembers(@NotNull String s) {
|
||||
|
||||
}
|
||||
|
||||
public ClassWithExternalAnnotatedMembers(Boolean b) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: usage.kt
|
||||
fun test() {
|
||||
val i: Int? = null
|
||||
ClassWithExternalAnnotatedMembers(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>i<!>)
|
||||
|
||||
val s: String? = null
|
||||
ClassWithExternalAnnotatedMembers(<!TYPE_MISMATCH!>s<!>)
|
||||
|
||||
val b: Boolean? = null
|
||||
ClassWithExternalAnnotatedMembers(b)
|
||||
|
||||
<!OVERLOAD_RESOLUTION_AMBIGUITY!>ClassWithExternalAnnotatedMembers<!>(null)
|
||||
}
|
||||
|
||||
// FILE: annotations.xml
|
||||
<root>
|
||||
<item name='ClassWithExternalAnnotatedMembers ClassWithExternalAnnotatedMembers(java.lang.Integer) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// FILE: ClassWithExternalAnnotatedMembers.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
public ClassWithExternalAnnotatedMembers(Integer i) { // with external annotation on parameter
|
||||
|
||||
}
|
||||
|
||||
public ClassWithExternalAnnotatedMembers(@NotNull String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: usage.kt
|
||||
fun test() {
|
||||
val i: Int? = null
|
||||
<!NONE_APPLICABLE!>ClassWithExternalAnnotatedMembers<!>(i)
|
||||
|
||||
val s: String? = null
|
||||
<!NONE_APPLICABLE!>ClassWithExternalAnnotatedMembers<!>(s)
|
||||
|
||||
val b: Boolean? = null
|
||||
<!NONE_APPLICABLE!>ClassWithExternalAnnotatedMembers<!>(b)
|
||||
|
||||
<!NONE_APPLICABLE!>ClassWithExternalAnnotatedMembers<!>(null)
|
||||
}
|
||||
|
||||
// FILE: annotations.xml
|
||||
<root>
|
||||
<item name='ClassWithExternalAnnotatedMembers ClassWithExternalAnnotatedMembers(java.lang.Integer) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// FILE: ClassWithExternalAnnotatedMembers.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
public ClassWithExternalAnnotatedMembers(Integer i) { // with external annotation on parameter
|
||||
|
||||
}
|
||||
|
||||
public ClassWithExternalAnnotatedMembers(@NotNull String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: usage.kt
|
||||
fun test() {
|
||||
val i: Int? = null
|
||||
ClassWithExternalAnnotatedMembers(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>i<!>)
|
||||
|
||||
val s: String? = null
|
||||
ClassWithExternalAnnotatedMembers(<!TYPE_MISMATCH!>s<!>)
|
||||
|
||||
val b: Boolean? = null
|
||||
<!NONE_APPLICABLE!>ClassWithExternalAnnotatedMembers<!>(b)
|
||||
|
||||
ClassWithExternalAnnotatedMembers(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
}
|
||||
|
||||
// FILE: annotations.xml
|
||||
<root>
|
||||
<item name='ClassWithExternalAnnotatedMembers ClassWithExternalAnnotatedMembers(java.lang.Integer) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
// FIR_IDENTICAL
|
||||
// FILE: ClassWithExternalAnnotatedMembers.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
public String externalNotNullField;
|
||||
|
||||
@NotNull
|
||||
public String explicitNotNullField;
|
||||
|
||||
public static String staticExternalNotNullField;
|
||||
|
||||
@NotNull
|
||||
public static String staticExplicitNotNullField;
|
||||
}
|
||||
|
||||
// FILE: usage.kt
|
||||
fun test() {
|
||||
val x = ClassWithExternalAnnotatedMembers()
|
||||
x.externalNotNullField<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
x.explicitNotNullField<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
|
||||
ClassWithExternalAnnotatedMembers.staticExternalNotNullField<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
ClassWithExternalAnnotatedMembers.staticExplicitNotNullField<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
}
|
||||
|
||||
fun String.foo() {
|
||||
|
||||
}
|
||||
|
||||
// FILE: annotations.xml
|
||||
<root>
|
||||
<item name='ClassWithExternalAnnotatedMembers externalNotNullField'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='ClassWithExternalAnnotatedMembers staticExternalNotNullField'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// FIR_IDENTICAL
|
||||
// FILE: one/two/ClassWithExternalAnnotatedMembers.java
|
||||
package one.two;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
public String externalNotNullField;
|
||||
|
||||
@NotNull
|
||||
public String explicitNotNullField;
|
||||
|
||||
public static String staticExternalNotNullField;
|
||||
|
||||
@NotNull
|
||||
public static String staticExplicitNotNullField;
|
||||
}
|
||||
|
||||
// FILE: one/usage.kt
|
||||
package one
|
||||
|
||||
import one.two.ClassWithExternalAnnotatedMembers
|
||||
|
||||
fun test() {
|
||||
val x = ClassWithExternalAnnotatedMembers()
|
||||
x.externalNotNullField<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
x.explicitNotNullField<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
|
||||
ClassWithExternalAnnotatedMembers.staticExternalNotNullField<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
ClassWithExternalAnnotatedMembers.staticExplicitNotNullField<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
}
|
||||
|
||||
fun String.foo() {
|
||||
|
||||
}
|
||||
|
||||
// FILE: one/two/annotations.xml
|
||||
<root>
|
||||
<item name='one.two.ClassWithExternalAnnotatedMembers externalNotNullField'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='one.two.ClassWithExternalAnnotatedMembers staticExternalNotNullField'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
Vendored
+47
@@ -0,0 +1,47 @@
|
||||
// FIR_IDENTICAL
|
||||
// FILE: ClassWithExternalAnnotatedMembers.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
public String externalNotNullMethod() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String explicitNotNullMethod() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String staticExternalNotNullMethod() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String staticExplicitNotNullMethod() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: usage.kt
|
||||
fun test() {
|
||||
val x = ClassWithExternalAnnotatedMembers()
|
||||
x.externalNotNullMethod()<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
x.explicitNotNullMethod()<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
|
||||
ClassWithExternalAnnotatedMembers.staticExternalNotNullMethod()<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
ClassWithExternalAnnotatedMembers.staticExplicitNotNullMethod()<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
}
|
||||
|
||||
fun String.foo() {
|
||||
|
||||
}
|
||||
|
||||
// FILE: annotations.xml
|
||||
<root>
|
||||
<item name='ClassWithExternalAnnotatedMembers java.lang.String externalNotNullMethod()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='ClassWithExternalAnnotatedMembers java.lang.String staticExternalNotNullMethod()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
// FIR_IDENTICAL
|
||||
// MODULE: javaModule
|
||||
// FILE: one/two/FirstModuleClass.java
|
||||
package one.two;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class FirstModuleClass {
|
||||
public String externalNotNullMethod() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String explicitNotNullMethod() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
// FILE: one/two/annotations.xml
|
||||
<root>
|
||||
<item name='one.two.FirstModuleClass java.lang.String externalNotNullMethod()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
// FILE: usage.kt
|
||||
package usage1
|
||||
|
||||
import one.two.FirstModuleClass
|
||||
|
||||
fun test() {
|
||||
val x = FirstModuleClass()
|
||||
x.externalNotNullMethod()<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
x.explicitNotNullMethod()<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
}
|
||||
|
||||
fun String.foo() {
|
||||
|
||||
}
|
||||
// MODULE: javaModule2
|
||||
// FILE: three/SecondModuleClass.java
|
||||
package three;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SecondModuleClass {
|
||||
public static String staticExternalNotNullMethod() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String staticExplicitNotNullMethod() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
// FILE: three/annotations.xml
|
||||
<root>
|
||||
<item name='three.SecondModuleClass java.lang.String staticExternalNotNullMethod()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
// FILE: my/pack/usage.kt
|
||||
package my.pack
|
||||
|
||||
import three.SecondModuleClass
|
||||
|
||||
fun test() {
|
||||
SecondModuleClass.staticExternalNotNullMethod()<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
SecondModuleClass.staticExplicitNotNullMethod()<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
|
||||
}
|
||||
|
||||
fun String.foo() {
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// FILE: ClassWithExternalAnnotatedMembers.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
public void method(String s) {
|
||||
}
|
||||
|
||||
public void method(@NotNull Integer i) {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: usage.kt
|
||||
fun test() {
|
||||
val instance = ClassWithExternalAnnotatedMembers()
|
||||
val i: Int? = null
|
||||
instance.<!NONE_APPLICABLE!>method<!>(i)
|
||||
|
||||
val s: String? = null
|
||||
instance.<!NONE_APPLICABLE!>method<!>(s)
|
||||
|
||||
val b: Boolean? = null
|
||||
instance.<!NONE_APPLICABLE!>method<!>(b)
|
||||
|
||||
instance.<!NONE_APPLICABLE!>method<!>(null)
|
||||
}
|
||||
|
||||
// FILE: annotations.xml
|
||||
<root>
|
||||
<item name='ClassWithExternalAnnotatedMembers void method(java.lang.String) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// FILE: ClassWithExternalAnnotatedMembers.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
public void method(String s) {
|
||||
}
|
||||
|
||||
public void method(@NotNull Integer i) {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: usage.kt
|
||||
fun test() {
|
||||
val instance = ClassWithExternalAnnotatedMembers()
|
||||
val i: Int? = null
|
||||
instance.method(<!TYPE_MISMATCH!>i<!>)
|
||||
|
||||
val s: String? = null
|
||||
instance.method(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>s<!>)
|
||||
|
||||
val b: Boolean? = null
|
||||
instance.<!NONE_APPLICABLE!>method<!>(b)
|
||||
|
||||
instance.method(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
}
|
||||
|
||||
// FILE: annotations.xml
|
||||
<root>
|
||||
<item name='ClassWithExternalAnnotatedMembers void method(java.lang.String) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// FILE: ClassWithExternalAnnotatedMembers.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
public void method(String s) {
|
||||
}
|
||||
|
||||
public void method(@NotNull Integer i) {
|
||||
}
|
||||
|
||||
public void method(Boolean b) {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: usage.kt
|
||||
fun test() {
|
||||
val instance = ClassWithExternalAnnotatedMembers()
|
||||
val i: Int? = null
|
||||
instance.<!NONE_APPLICABLE!>method<!>(i)
|
||||
|
||||
val s: String? = null
|
||||
instance.<!NONE_APPLICABLE!>method<!>(s)
|
||||
|
||||
val b: Boolean? = null
|
||||
instance.method(b)
|
||||
|
||||
instance.method(null)
|
||||
}
|
||||
|
||||
// FILE: annotations.xml
|
||||
<root>
|
||||
<item name='ClassWithExternalAnnotatedMembers void method(java.lang.String) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// FILE: ClassWithExternalAnnotatedMembers.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ClassWithExternalAnnotatedMembers {
|
||||
public void method(String s) {
|
||||
}
|
||||
|
||||
public void method(@NotNull Integer i) {
|
||||
}
|
||||
|
||||
public void method(Boolean b) {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: usage.kt
|
||||
fun test() {
|
||||
val instance = ClassWithExternalAnnotatedMembers()
|
||||
val i: Int? = null
|
||||
instance.method(<!TYPE_MISMATCH!>i<!>)
|
||||
|
||||
val s: String? = null
|
||||
instance.method(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>s<!>)
|
||||
|
||||
val b: Boolean? = null
|
||||
instance.method(b)
|
||||
|
||||
instance.<!OVERLOAD_RESOLUTION_AMBIGUITY!>method<!>(null)
|
||||
}
|
||||
|
||||
// FILE: annotations.xml
|
||||
<root>
|
||||
<item name='ClassWithExternalAnnotatedMembers void method(java.lang.String) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
+1
-1
@@ -23,7 +23,7 @@ public class ForeignAnnotationsCompiledJavaTestGenerated extends AbstractForeign
|
||||
public class Tests {
|
||||
@Test
|
||||
public void testAllFilesPresentInTests() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "externalAnnotations");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+58
@@ -146,6 +146,64 @@ public class ForeignAnnotationsCompiledJavaWithPsiClassReadingTestGenerated exte
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/rxjava3Warnings.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ExternalAnnotations {
|
||||
@Test
|
||||
public void testAllFilesPresentInExternalAnnotations() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorParameterNotNull.kt")
|
||||
public void testConstructorParameterNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/constructorParameterNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorParameterNotNull2.kt")
|
||||
public void testConstructorParameterNotNull2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/constructorParameterNotNull2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fieldNotNull.kt")
|
||||
public void testFieldNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/fieldNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fieldNotNullAnnotationWithPackage.kt")
|
||||
public void testFieldNotNullAnnotationWithPackage() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/fieldNotNullAnnotationWithPackage.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodNotNull.kt")
|
||||
public void testMethodNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodNotNullFromAnotherModule.kt")
|
||||
public void testMethodNotNullFromAnotherModule() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodNotNullFromAnotherModule.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodParameterNotNull.kt")
|
||||
public void testMethodParameterNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodParameterNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodParameterNotNull2.kt")
|
||||
public void testMethodParameterNotNull2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodParameterNotNull2.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/foreignAnnotationsTests/tests/jsr305")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+58
@@ -146,6 +146,64 @@ public class ForeignAnnotationsSourceJavaTestGenerated extends AbstractForeignAn
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/rxjava3Warnings.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ExternalAnnotations {
|
||||
@Test
|
||||
public void testAllFilesPresentInExternalAnnotations() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorParameterNotNull.kt")
|
||||
public void testConstructorParameterNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/constructorParameterNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("constructorParameterNotNull2.kt")
|
||||
public void testConstructorParameterNotNull2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/constructorParameterNotNull2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fieldNotNull.kt")
|
||||
public void testFieldNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/fieldNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fieldNotNullAnnotationWithPackage.kt")
|
||||
public void testFieldNotNullAnnotationWithPackage() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/fieldNotNullAnnotationWithPackage.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodNotNull.kt")
|
||||
public void testMethodNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodNotNullFromAnotherModule.kt")
|
||||
public void testMethodNotNullFromAnotherModule() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodNotNullFromAnotherModule.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodParameterNotNull.kt")
|
||||
public void testMethodParameterNotNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodParameterNotNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodParameterNotNull2.kt")
|
||||
public void testMethodParameterNotNull2() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/externalAnnotations/methodParameterNotNull2.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/foreignAnnotationsTests/tests/jsr305")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.test.preprocessors
|
||||
|
||||
import org.jetbrains.kotlin.test.model.TestFile
|
||||
import org.jetbrains.kotlin.test.services.ReversibleSourceFilePreprocessor
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.isExternalAnnotation
|
||||
|
||||
/**
|
||||
* This preprocessor is required to drop '//' comments from the file to avoid exceptions from XML parser
|
||||
*/
|
||||
class ExternalAnnotationsSourcePreprocessor(testServices: TestServices) : ReversibleSourceFilePreprocessor(testServices) {
|
||||
override fun process(file: TestFile, content: String): String = if (file.isExternalAnnotation) {
|
||||
content.trim().lineSequence().filterNot { it.startsWith('/') }.joinToString(separator = "\n")
|
||||
} else {
|
||||
content
|
||||
}
|
||||
|
||||
override fun revert(file: TestFile, actualContent: String): String {
|
||||
return if (file.isExternalAnnotation) file.originalContent.trim() + "\n" else actualContent
|
||||
}
|
||||
}
|
||||
+7
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,9 @@ import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirective
|
||||
import org.jetbrains.kotlin.test.frontend.classic.handlers.*
|
||||
import org.jetbrains.kotlin.test.model.DependencyKind
|
||||
import org.jetbrains.kotlin.test.model.FrontendKinds
|
||||
import org.jetbrains.kotlin.test.preprocessors.ExternalAnnotationsSourcePreprocessor
|
||||
import org.jetbrains.kotlin.test.preprocessors.JspecifyMarksCleanupPreprocessor
|
||||
import org.jetbrains.kotlin.test.services.SourceFilePreprocessor
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.configuration.*
|
||||
import org.jetbrains.kotlin.test.services.jvm.ForeignAnnotationAgainstCompiledJavaTestSuppressor
|
||||
@@ -69,9 +71,12 @@ abstract class AbstractForeignAnnotationsTestBase(private val kind: ForeignAnnot
|
||||
useConfigurators(
|
||||
::CommonEnvironmentConfigurator,
|
||||
::JvmForeignAnnotationsConfigurator,
|
||||
::JvmEnvironmentConfigurator
|
||||
::JvmEnvironmentConfigurator,
|
||||
::ExternalAnnotationsEnvironmentConfigurator,
|
||||
)
|
||||
|
||||
useSourcePreprocessor(::ExternalAnnotationsSourcePreprocessor)
|
||||
|
||||
useAdditionalSourceProviders(
|
||||
::AdditionalDiagnosticsSourceFilesProvider,
|
||||
::CoroutineHelpersSourceFilesProvider,
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.test.services.configuration
|
||||
|
||||
import com.intellij.codeInsight.BaseExternalAnnotationsManager
|
||||
import com.intellij.codeInsight.ExternalAnnotationsManager
|
||||
import com.intellij.mock.MockProject
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.PsiModifierListOwner
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.EnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.sourceFileProvider
|
||||
|
||||
/**
|
||||
* Adds the ability to declare 'annotations.xml' file with description of external annotations.
|
||||
*
|
||||
* Such synthetic Java annotations can be found by
|
||||
* [JavaAnnotation.isIdeExternalAnnotation][org.jetbrains.kotlin.load.java.structure.JavaAnnotation.isIdeExternalAnnotation] flag.
|
||||
*
|
||||
* @see ExternalAnnotationsManager
|
||||
* @see org.jetbrains.kotlin.test.preprocessors.ExternalAnnotationsSourcePreprocessor
|
||||
*/
|
||||
class ExternalAnnotationsEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) {
|
||||
override fun legacyRegisterCompilerExtensions(project: Project, module: TestModule, configuration: CompilerConfiguration) {
|
||||
var hasAnnotationFile = false
|
||||
for (file in module.files) {
|
||||
if (file.name != ExternalAnnotationsManager.ANNOTATIONS_XML) continue
|
||||
|
||||
// This call is required to copy files into the project to be able to read those xml files from the manager
|
||||
testServices.sourceFileProvider.getRealFileForSourceFile(file)
|
||||
hasAnnotationFile = true
|
||||
}
|
||||
|
||||
if (!hasAnnotationFile) return
|
||||
|
||||
(project as MockProject).picoContainer.unregisterComponent(ExternalAnnotationsManager::class.java.name)
|
||||
project.registerService(
|
||||
ExternalAnnotationsManager::class.java,
|
||||
ExternalAnnotationsManagerForTests(
|
||||
// We use additionalFilesDirectory as a root of external annotations because this directory contains all
|
||||
// declared 'annotations.xml' files
|
||||
externalAnnotationsRootPath = testServices.sourceFileProvider.additionalFilesDirectory.path,
|
||||
manager = PsiManager.getInstance(project),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple [ExternalAnnotationsManager] implementation
|
||||
* which always suggests searching external annotations inside [externalAnnotationsRootPath].
|
||||
*
|
||||
* @param externalAnnotationsRootPath path to the directory with 'annotations.xml' files
|
||||
*/
|
||||
private class ExternalAnnotationsManagerForTests(
|
||||
externalAnnotationsRootPath: String,
|
||||
manager: PsiManager,
|
||||
) : BaseExternalAnnotationsManager(manager) {
|
||||
private val externalAnnotationsRoots: List<VirtualFile> by lazyPub {
|
||||
VirtualFileManager.getInstance()
|
||||
.getFileSystem(StandardFileSystems.FILE_PROTOCOL)
|
||||
.findFileByPath(externalAnnotationsRootPath)
|
||||
?.let(::listOf)
|
||||
?: error("File with external annotations is not found")
|
||||
}
|
||||
|
||||
/**
|
||||
* We simply returns [externalAnnotationsRoots] because there is all our declared 'annotations.xml' files
|
||||
*
|
||||
* @param libraryFile is a file for which we want to find the corresponding external annotations file if it exists
|
||||
*/
|
||||
override fun getExternalAnnotationsRoots(libraryFile: VirtualFile): List<VirtualFile> = externalAnnotationsRoots
|
||||
|
||||
override fun hasAnyAnnotationsRoots(): Boolean = true
|
||||
override fun hasConfiguredAnnotationRoot(owner: PsiModifierListOwner): Boolean = true
|
||||
}
|
||||
+1
-1
@@ -46,7 +46,7 @@ class ModuleStructureExtractorImpl(
|
||||
private val environmentConfigurators: List<AbstractEnvironmentConfigurator>
|
||||
) : ModuleStructureExtractor(testServices, additionalSourceProviders, moduleStructureTransformers) {
|
||||
companion object {
|
||||
private val allowedExtensionsForFiles = listOf(".kt", ".kts", ".java", ".js", ".mjs", ".config")
|
||||
private val allowedExtensionsForFiles = listOf(".kt", ".kts", ".java", ".js", ".mjs", ".config", ".xml")
|
||||
|
||||
/*
|
||||
* ([^()\n]+) module name
|
||||
|
||||
+10
-2
@@ -56,7 +56,11 @@ fun generateJUnit5CompilerTests(args: Array<String>, mainClassName: String?) {
|
||||
}
|
||||
|
||||
testClass<AbstractForeignAnnotationsCompiledJavaTest> {
|
||||
model("diagnostics/foreignAnnotationsTests/tests", excludedPattern = excludedCustomTestdataPattern)
|
||||
model(
|
||||
"diagnostics/foreignAnnotationsTests/tests",
|
||||
excludedPattern = excludedCustomTestdataPattern,
|
||||
excludeDirs = listOf("externalAnnotations"),
|
||||
)
|
||||
model("diagnostics/foreignAnnotationsTests/java8Tests", excludedPattern = excludedCustomTestdataPattern)
|
||||
model("diagnostics/foreignAnnotationsTests/java11Tests", excludedPattern = excludedCustomTestdataPattern)
|
||||
}
|
||||
@@ -242,7 +246,11 @@ fun generateJUnit5CompilerTests(args: Array<String>, mainClassName: String?) {
|
||||
testClass<AbstractFirPsiForeignAnnotationsCompiledJavaTest>(
|
||||
suiteTestClassName = "FirPsiOldFrontendForeignAnnotationsCompiledJavaTestGenerated"
|
||||
) {
|
||||
model("diagnostics/foreignAnnotationsTests/tests", excludedPattern = excludedCustomTestdataPattern)
|
||||
model(
|
||||
"diagnostics/foreignAnnotationsTests/tests",
|
||||
excludedPattern = excludedCustomTestdataPattern,
|
||||
excludeDirs = listOf("externalAnnotations"),
|
||||
)
|
||||
model("diagnostics/foreignAnnotationsTests/java8Tests", excludedPattern = excludedCustomTestdataPattern)
|
||||
model("diagnostics/foreignAnnotationsTests/java11Tests", excludedPattern = excludedCustomTestdataPattern)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user