mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-04 17:20:55 +07:00
junit 5: support references between kotlin and java (IDEA-248355)
GitOrigin-RevId: 7db4cb465500beed1e79f0262a785c0653424d12
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a4022dc65d
commit
339e65fcd2
@@ -11,5 +11,6 @@
|
||||
<orderEntry type="library" scope="RUNTIME" name="KotlinPlugin" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="kotlin-stdlib-jdk8" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.java.tests" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.junit" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,8 @@
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
class KtMethodSourceUsage {
|
||||
@ParameterizedTest
|
||||
@MethodSource("SampleTest#squares")
|
||||
void testSquares(int input, int expected) {}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInspection
|
||||
|
||||
import com.intellij.execution.junit.codeInsight.JUnit5MalformedParameterizedInspection
|
||||
import com.intellij.execution.junit.codeInsight.JUnit5TestFrameworkSetupUtil
|
||||
import com.intellij.jvm.analysis.JvmAnalysisKtTestsUtil
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import com.siyeh.ig.LightJavaInspectionTestCase
|
||||
|
||||
class KotlinJUnit5MalformedParameterizedTest : LightJavaInspectionTestCase() {
|
||||
override fun getInspection(): InspectionProfileEntry? {
|
||||
return JUnit5MalformedParameterizedInspection()
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
myFixture.addFileToProject("kotlin/jvm/JvmStatic.kt",
|
||||
"package kotlin.jvm public annotation class JvmStatic")
|
||||
myFixture.addFileToProject("SampleTest.kt", """open class SampleTest {
|
||||
companion object {
|
||||
@kotlin.jvm.JvmStatic
|
||||
fun squares() : List<org.junit.jupiter.params.provider.Arguments> {
|
||||
return listOf(
|
||||
org.junit.jupiter.params.provider.Arguments.of(1, 1)
|
||||
)
|
||||
}
|
||||
}
|
||||
}""")
|
||||
JUnit5TestFrameworkSetupUtil.setupJUnit5Library(myFixture)
|
||||
}
|
||||
|
||||
fun testKtMethodSourceUsage() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
override fun getBasePath() =
|
||||
"${JvmAnalysisKtTestsUtil.TEST_DATA_PROJECT_RELATIVE_BASE_PATH}/codeInspection/junit5malformed"
|
||||
|
||||
|
||||
override fun getProjectDescriptor(): LightProjectDescriptor {
|
||||
return JAVA_8
|
||||
}
|
||||
}
|
||||
@@ -10,20 +10,20 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import com.intellij.psi.filters.position.FilterPattern;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.siyeh.ig.junit.JUnitCommonClassNames;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.uast.*;
|
||||
|
||||
public class JUnitReferenceContributor extends PsiReferenceContributor {
|
||||
private static PsiElementPattern.Capture<PsiLiteral> getElementPattern(String annotation, String paramName) {
|
||||
return PlatformPatterns.psiElement(PsiLiteral.class).and(new FilterPattern(new TestAnnotationFilter(annotation, paramName)));
|
||||
private static PsiElementPattern.Capture<PsiElement> getElementPattern(String annotation, String paramName) {
|
||||
return PlatformPatterns.psiElement(PsiElement.class).and(new FilterPattern(new TestAnnotationFilter(annotation, paramName)));
|
||||
}
|
||||
|
||||
private static PsiElementPattern.Capture<PsiLiteral> getEnumSourceNamesPattern() {
|
||||
private static PsiElementPattern.Capture<PsiElement> getEnumSourceNamesPattern() {
|
||||
return getElementPattern(JUnitCommonClassNames.ORG_JUNIT_JUPITER_PARAMS_ENUM_SOURCE, "names")
|
||||
.withAncestor(4, PlatformPatterns.psiElement(PsiAnnotation.class).and(new PsiJavaElementPattern<>(new InitialPatternCondition<PsiAnnotation>(PsiAnnotation.class) {
|
||||
@Override
|
||||
@@ -45,7 +45,7 @@ public class JUnitReferenceContributor extends PsiReferenceContributor {
|
||||
registrar.registerReferenceProvider(getElementPattern(JUnitCommonClassNames.ORG_JUNIT_JUPITER_PARAMS_PROVIDER_METHOD_SOURCE, "value"), new PsiReferenceProvider() {
|
||||
@Override
|
||||
public PsiReference @NotNull [] getReferencesByElement(@NotNull PsiElement element, @NotNull final ProcessingContext context) {
|
||||
return new MethodSourceReference[]{new MethodSourceReference((PsiLiteral)element)};
|
||||
return new MethodSourceReference[]{new MethodSourceReference(UastContextKt.toUElement(element, UExpression.class), (PsiLanguageInjectionHost)element)};
|
||||
}
|
||||
});
|
||||
registrar.registerReferenceProvider(getEnumSourceNamesPattern(), new PsiReferenceProvider() {
|
||||
@@ -74,18 +74,20 @@ public class JUnitReferenceContributor extends PsiReferenceContributor {
|
||||
|
||||
@Override
|
||||
public boolean isAcceptable(Object element, PsiElement context) {
|
||||
PsiNameValuePair pair = PsiTreeUtil.getParentOfType(context, PsiNameValuePair.class, false, PsiMember.class, PsiStatement.class, PsiCall.class);
|
||||
if (pair == null) return false;
|
||||
String name = ObjectUtils.notNull(pair.getName(), PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME);
|
||||
UElement type = UastContextKt.toUElement(context, UElement.class);
|
||||
if (type == null) return false;
|
||||
UNamedExpression uPair = UastUtils.getParentOfType(type, UNamedExpression.class);
|
||||
if (uPair == null) return false;
|
||||
String name = ObjectUtils.notNull(uPair.getName(), PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME);
|
||||
if (!myParameterName.equals(name)) return false;
|
||||
PsiAnnotation annotation = PsiTreeUtil.getParentOfType(pair, PsiAnnotation.class);
|
||||
if (annotation == null) return false;
|
||||
return myAnnotation.equals(annotation.getQualifiedName());
|
||||
UAnnotation uAnnotation = UastUtils.getParentOfType(type, UAnnotation.class);
|
||||
if (uAnnotation == null) return false;
|
||||
return myAnnotation.equals(uAnnotation.getQualifiedName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClassAcceptable(Class hintClass) {
|
||||
return PsiLiteral.class.isAssignableFrom(hintClass);
|
||||
return PsiLanguageInjectionHost.class.isAssignableFrom(hintClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,14 @@ import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.ClassUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.ig.psiutils.TestUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.uast.UClass;
|
||||
import org.jetbrains.uast.UExpression;
|
||||
import org.jetbrains.uast.UMethod;
|
||||
import org.jetbrains.uast.UastUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -32,10 +35,12 @@ import java.util.List;
|
||||
|
||||
import static com.intellij.psi.CommonClassNames.JAVA_LANG_OBJECT;
|
||||
|
||||
public class MethodSourceReference extends PsiReferenceBase<PsiLiteral> {
|
||||
public class MethodSourceReference extends PsiReferenceBase<PsiLanguageInjectionHost> {
|
||||
private final UExpression myLiteral;
|
||||
|
||||
public MethodSourceReference(PsiLiteral element) {
|
||||
public MethodSourceReference(UExpression uLiteral, PsiLanguageInjectionHost element) {
|
||||
super(element, false);
|
||||
myLiteral = uLiteral;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,47 +56,49 @@ public class MethodSourceReference extends PsiReferenceBase<PsiLiteral> {
|
||||
String methodName = getValue();
|
||||
String className = StringUtil.getPackageName(methodName, '#');
|
||||
boolean selfClassReference = className.isEmpty() ||
|
||||
ClassUtil.findPsiClass(getElement().getManager(), className, null, false, getElement().getResolveScope()) == null;
|
||||
ClassUtil
|
||||
.findPsiClass(getElement().getManager(), className, null, false, getElement().getResolveScope()) == null;
|
||||
return super.handleElementRename(selfClassReference ? newElementName : className + '#' + newElementName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement resolve() {
|
||||
PsiClass cls = PsiTreeUtil.getParentOfType(getElement(), PsiClass.class);
|
||||
if (cls != null) {
|
||||
String methodName = getValue();
|
||||
String className = StringUtil.getPackageName(methodName, '#');
|
||||
if (!className.isEmpty()) {
|
||||
PsiClass aClass = ClassUtil.findPsiClass(cls.getManager(), className, null, false, cls.getResolveScope());
|
||||
if (aClass != null) {
|
||||
cls = aClass;
|
||||
methodName = StringUtil.getShortName(methodName, '#');
|
||||
}
|
||||
UClass clazz = UastUtils.getParentOfType(myLiteral, UClass.class);
|
||||
if (clazz == null) return null;
|
||||
PsiClass psiClazz = clazz.getPsi();
|
||||
String methodName = (String)myLiteral.evaluate();
|
||||
if (methodName == null) return null;
|
||||
String className = StringUtil.getPackageName(methodName, '#');
|
||||
if (!className.isEmpty()) {
|
||||
PsiClass aClass = ClassUtil.findPsiClass(psiClazz.getManager(), className, null, false, psiClazz.getResolveScope());
|
||||
if (aClass != null) {
|
||||
psiClazz = aClass;
|
||||
methodName = StringUtil.getShortName(methodName, '#');
|
||||
}
|
||||
PsiMethod[] methods = cls.findMethodsByName(methodName, true);
|
||||
final PsiClass finalCls = cls;
|
||||
return Arrays.stream(methods)
|
||||
.filter(method -> staticOrOneInstancePerClassNoParams(method, finalCls))
|
||||
.findFirst()
|
||||
.orElse(methods.length == 0 ? null : methods[0]);
|
||||
}
|
||||
return null;
|
||||
PsiMethod[] clazzMethods = psiClazz.findMethodsByName(methodName, true);
|
||||
final PsiClass finalCls = psiClazz;
|
||||
return Arrays.stream(clazzMethods)
|
||||
.filter(method -> staticOrOneInstancePerClassNoParams(method, finalCls))
|
||||
.findFirst()
|
||||
.orElse(clazzMethods.length == 0 ? null : clazzMethods[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object @NotNull [] getVariants() {
|
||||
final List<Object> list = new ArrayList<>();
|
||||
final PsiClass topLevelClass = PsiTreeUtil.getParentOfType(getElement(), PsiClass.class);
|
||||
final UClass topLevelClass = UastUtils.getParentOfType(myLiteral, UClass.class);
|
||||
if (topLevelClass != null) {
|
||||
final PsiMethod current = PsiTreeUtil.getParentOfType(getElement(), PsiMethod.class);
|
||||
final PsiMethod[] methods = topLevelClass.getAllMethods();
|
||||
final UMethod current = UastUtils.getParentOfType(myLiteral, UMethod.class);
|
||||
PsiClass psiTopLevelClass = topLevelClass.getJavaPsi();
|
||||
final PsiMethod[] methods = psiTopLevelClass.getAllMethods();
|
||||
for (PsiMethod method : methods) {
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) continue;
|
||||
if (JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) continue;
|
||||
if (current != null && method.getName().equals(current.getName())) continue;
|
||||
if (!staticOrOneInstancePerClassNoParams(method, topLevelClass)) continue;
|
||||
if (!staticOrOneInstancePerClassNoParams(method, psiTopLevelClass)) continue;
|
||||
final LookupElementBuilder builder = LookupElementBuilder.create(method);
|
||||
list.add(builder.withAutoCompletionPolicy(AutoCompletionPolicy.SETTINGS_DEPENDENT));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user