From 1355cc20aead4da37445a135214963f33fb43716 Mon Sep 17 00:00:00 2001 From: siosio Date: Thu, 30 Jun 2022 06:07:12 +0900 Subject: [PATCH] :sparkles: add kotlin step impl support --- gauge/build.gradle | 2 +- gauge/resources/META-INF/plugin.xml | 1 + gauge/resources/META-INF/with-kotlin.xml | 2 + .../com/thoughtworks/gauge/GaugeBundle.java | 7 +- .../CustomFindUsagesHandlerFactory.java | 3 + .../gauge/findUsages/ImplUsageProvider.java | 2 + .../helper/ReferenceSearchHelper.java | 12 ++- .../thoughtworks/gauge/util/GaugeUtil.java | 11 ++- .../com/thoughtworks/gauge/util/KtUtil.java | 89 +++++++++++++++++++ .../com/thoughtworks/gauge/util/StepUtil.java | 2 +- 10 files changed, 119 insertions(+), 12 deletions(-) create mode 100644 gauge/resources/META-INF/with-kotlin.xml create mode 100644 gauge/src/com/thoughtworks/gauge/util/KtUtil.java diff --git a/gauge/build.gradle b/gauge/build.gradle index 6799f3878c9..dbc4facc586 100644 --- a/gauge/build.gradle +++ b/gauge/build.gradle @@ -33,7 +33,7 @@ intellij { localPath = ideaPath } - plugins = ['java', 'properties', 'maven', 'gradle'] + plugins = ['java', 'properties', 'maven', 'gradle', 'Kotlin'] } patchPluginXml { } diff --git a/gauge/resources/META-INF/plugin.xml b/gauge/resources/META-INF/plugin.xml index 130b7a8b9ed..d93963da592 100644 --- a/gauge/resources/META-INF/plugin.xml +++ b/gauge/resources/META-INF/plugin.xml @@ -10,6 +10,7 @@ org.jetbrains.plugins.gradle org.jetbrains.idea.maven + org.jetbrains.kotlin Gauge tests (originally developed by Thoughtworks Inc.). diff --git a/gauge/resources/META-INF/with-kotlin.xml b/gauge/resources/META-INF/with-kotlin.xml new file mode 100644 index 00000000000..6fb76a66265 --- /dev/null +++ b/gauge/resources/META-INF/with-kotlin.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/gauge/src/com/thoughtworks/gauge/GaugeBundle.java b/gauge/src/com/thoughtworks/gauge/GaugeBundle.java index 825cce48241..d8863a6af21 100644 --- a/gauge/src/com/thoughtworks/gauge/GaugeBundle.java +++ b/gauge/src/com/thoughtworks/gauge/GaugeBundle.java @@ -16,15 +16,14 @@ package com.thoughtworks.gauge; +import java.util.function.Supplier; + import com.intellij.DynamicBundle; import com.intellij.openapi.util.NlsSafe; import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.PropertyKey; -import java.util.function.Supplier; - public final class GaugeBundle extends DynamicBundle { public static final @NlsSafe String GAUGE = "Gauge"; @@ -41,7 +40,7 @@ private GaugeBundle() { } @NotNull - public static Supplier<@Nls String> messagePointer(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, + public static Supplier messagePointer(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) { return INSTANCE.getLazyMessage(key, params); } diff --git a/gauge/src/com/thoughtworks/gauge/findUsages/CustomFindUsagesHandlerFactory.java b/gauge/src/com/thoughtworks/gauge/findUsages/CustomFindUsagesHandlerFactory.java index 1abef5a1f3c..be1db71b0d2 100644 --- a/gauge/src/com/thoughtworks/gauge/findUsages/CustomFindUsagesHandlerFactory.java +++ b/gauge/src/com/thoughtworks/gauge/findUsages/CustomFindUsagesHandlerFactory.java @@ -22,6 +22,7 @@ import com.intellij.psi.PsiMethod; import com.thoughtworks.gauge.language.psi.impl.ConceptStepImpl; import com.thoughtworks.gauge.language.psi.impl.SpecStepImpl; +import com.thoughtworks.gauge.util.KtUtil; import com.thoughtworks.gauge.util.StepUtil; import org.jetbrains.annotations.NotNull; @@ -30,6 +31,8 @@ public final class CustomFindUsagesHandlerFactory extends FindUsagesHandlerFacto public boolean canFindUsages(@NotNull PsiElement psiElement) { if (psiElement instanceof PsiMethod) { return StepUtil.getGaugeStepAnnotationValues((PsiMethod)psiElement).size() > 0; + } else if (KtUtil.isKtFunction(psiElement)) { + return KtUtil.getGaugeStepAnnotationValues(psiElement).size() > 0; } return psiElement instanceof SpecStepImpl || psiElement instanceof ConceptStepImpl; } diff --git a/gauge/src/com/thoughtworks/gauge/findUsages/ImplUsageProvider.java b/gauge/src/com/thoughtworks/gauge/findUsages/ImplUsageProvider.java index 454a541525e..8a6633624ae 100644 --- a/gauge/src/com/thoughtworks/gauge/findUsages/ImplUsageProvider.java +++ b/gauge/src/com/thoughtworks/gauge/findUsages/ImplUsageProvider.java @@ -25,6 +25,7 @@ import com.thoughtworks.gauge.helper.ModuleHelper; import com.thoughtworks.gauge.util.GaugeUtil; import com.thoughtworks.gauge.util.HookUtil; +import com.thoughtworks.gauge.util.KtUtil; import com.thoughtworks.gauge.util.StepUtil; import org.jetbrains.annotations.NotNull; @@ -41,6 +42,7 @@ public ImplUsageProvider() { public boolean isImplicitUsage(@NotNull PsiElement element) { if (!moduleHelper.isGaugeModule(element)) return false; if (element instanceof PsiClassImpl) return isClassUsed((PsiClassImpl)element); + if (KtUtil.isKtClass(element)) return KtUtil.isClassUsed(element); if (element instanceof PsiParameterImpl) return isParameterUsed((PsiParameterImpl)element); return isElementUsed(element); } diff --git a/gauge/src/com/thoughtworks/gauge/findUsages/helper/ReferenceSearchHelper.java b/gauge/src/com/thoughtworks/gauge/findUsages/helper/ReferenceSearchHelper.java index 83987d1b5ba..b4cfd36ae83 100644 --- a/gauge/src/com/thoughtworks/gauge/findUsages/helper/ReferenceSearchHelper.java +++ b/gauge/src/com/thoughtworks/gauge/findUsages/helper/ReferenceSearchHelper.java @@ -16,6 +16,9 @@ package com.thoughtworks.gauge.findUsages.helper; +import java.util.ArrayList; +import java.util.List; + import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.impl.source.PsiMethodImpl; @@ -27,12 +30,10 @@ import com.thoughtworks.gauge.language.psi.impl.ConceptStepImpl; import com.thoughtworks.gauge.language.psi.impl.SpecStepImpl; import com.thoughtworks.gauge.util.GaugeUtil; +import com.thoughtworks.gauge.util.KtUtil; import com.thoughtworks.gauge.util.StepUtil; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; - public class ReferenceSearchHelper { public static final String UNKNOWN_SCOPE = ""; @@ -68,6 +69,11 @@ else if (element instanceof PsiMethodImpl) { elements.addAll(collector.get(getStepText(alias, element))); } } + else if (KtUtil.isKtFunction(element) || KtUtil.isKtMethod(element)) { + for (String alias : KtUtil.getGaugeStepAnnotationValues(element)) { + elements.addAll(collector.get(getStepText(alias, element))); + } + } else if (element instanceof SpecStepImpl) { elements = collector.get(getStepText((SpecStepImpl)element)); elements.addAll(collector.get(((SpecStepImpl)element).getName())); diff --git a/gauge/src/com/thoughtworks/gauge/util/GaugeUtil.java b/gauge/src/com/thoughtworks/gauge/util/GaugeUtil.java index 5ead0799938..a74742b0f16 100644 --- a/gauge/src/com/thoughtworks/gauge/util/GaugeUtil.java +++ b/gauge/src/com/thoughtworks/gauge/util/GaugeUtil.java @@ -163,9 +163,14 @@ public static boolean isGradleModule(Module module) { } public static boolean isGaugeElement(PsiElement element) { - return StepUtil.isMethod(element) - ? StepUtil.getGaugeStepAnnotationValues((PsiMethod)element).size() > 0 - : (StepUtil.isConcept(element) || StepUtil.isStep(element)); + if (StepUtil.isMethod(element)) { + return StepUtil.getGaugeStepAnnotationValues((PsiMethod) element) + .size() > 0; + } else if (KtUtil.isKtFunction(element) || KtUtil.isKtMethod(element)) { + return KtUtil.getGaugeStepAnnotationValues(element).size() > 0; + } else { + return StepUtil.isConcept(element) || StepUtil.isStep(element); + } } @Nullable diff --git a/gauge/src/com/thoughtworks/gauge/util/KtUtil.java b/gauge/src/com/thoughtworks/gauge/util/KtUtil.java new file mode 100644 index 00000000000..e2693fff29f --- /dev/null +++ b/gauge/src/com/thoughtworks/gauge/util/KtUtil.java @@ -0,0 +1,89 @@ +package com.thoughtworks.gauge.util; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import org.jetbrains.kotlin.asJava.LightClassUtil; +import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass; +import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl; +import org.jetbrains.kotlin.psi.KtNamedFunction; + +public final class KtUtil { + + public static boolean isKtClass(PsiElement element) { + try { + return Class.forName("org.jetbrains.kotlin.asJava.classes.KtUltraLightClass").isInstance(element); + } catch (ClassNotFoundException e) { + return false; + } + } + + public static boolean isKtFunction(PsiElement element) { + try { + return Class.forName("org.jetbrains.kotlin.psi.KtNamedFunction").isInstance(element); + } catch (ClassNotFoundException e) { + return false; + } + } + + public static boolean isKtMethod(PsiElement element) { + try { + return Class.forName("org.jetbrains.kotlin.asJava.classes.KtUltraLightMethod") + .isInstance(element); + } catch (ClassNotFoundException e) { + return false; + } + } + + public static boolean isClassUsed(final PsiElement element) { + if (!isKtClass(element)) { + return false; + } + return Inner.isClassUsed(element); + } + + public static List getGaugeStepAnnotationValues(PsiElement element) { + return Inner.getGaugeStepAnnotationValues(element); + } + + public static final class Inner { + + private Inner() { + } + + private static boolean isClassUsed(final PsiElement element) { + if (!isKtClass(element)) { + return false; + } + return Arrays.stream(((KtUltraLightClass) element).getAllMethods()) + .anyMatch(function -> + StepUtil.getGaugeStepAnnotationValues(function).size() > 0 || HookUtil.isHook(function)); + } + + + private static List getGaugeStepAnnotationValues(PsiElement element) { + final PsiAnnotation[] annotations; + if (isKtFunction(element)) { + annotations = toPsiMethod((KtNamedFunction) element).getAnnotations(); + } else if (isKtMethod(element)) { + annotations = ((KtLightMethodImpl) element).getAnnotations(); + } else { + annotations = PsiAnnotation.EMPTY_ARRAY; + } + return Arrays.stream(annotations) + .map(StepUtil::getGaugeStepAnnotationValues) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + } + + private static PsiMethod toPsiMethod(KtNamedFunction function) { + return LightClassUtil.INSTANCE.getLightClassMethod(function); + } + + } +} diff --git a/gauge/src/com/thoughtworks/gauge/util/StepUtil.java b/gauge/src/com/thoughtworks/gauge/util/StepUtil.java index c6cbbb6f31b..85fd5848c5d 100644 --- a/gauge/src/com/thoughtworks/gauge/util/StepUtil.java +++ b/gauge/src/com/thoughtworks/gauge/util/StepUtil.java @@ -163,7 +163,7 @@ public static List getGaugeStepAnnotationValues(PsiMethod stepMethod) { return values; } - private static List getGaugeStepAnnotationValues(PsiAnnotation annotation) { + static List getGaugeStepAnnotationValues(PsiAnnotation annotation) { List values = new ArrayList<>(); if (!isGaugeAnnotation(annotation)) { return values;