From a615756b203eb1561fe2b2f74a107880401ca575 Mon Sep 17 00:00:00 2001 From: "igor.petrenko" Date: Tue, 2 Dec 2025 09:05:54 +0200 Subject: [PATCH] CE-118 goto parameter --- build.gradle.kts | 2 +- .../plugin/gen/parser/OapParser.java | 122 ++++-------------- .../OapModuleServicesServiceLinkField.java | 4 +- .../gen/psi/OapParameterKeyValueFirstId.java | 3 + .../plugin/gen/psi/OapVisitor.java | 2 +- .../impl/OapParameterKeyValueFirstIdImpl.java | 6 + grammars/oap.bnf | 11 +- .../JavaOapServiceLineMarkerProvider.kt | 2 +- .../OapParameterKeyValueFirstIdManipulator.kt | 17 +++ .../plugin/psi/impl/GrammarPsiImplUtil.kt | 34 +++++ .../psi/impl/JvmNamedElementReference.kt | 11 ++ .../plugin/ref/ValidParametersInspection.kt | 14 +- src/main/resources/META-INF/plugin.xml | 2 + .../plugin/gotoref/GotoParameterTest.kt | 45 +++++++ 14 files changed, 164 insertions(+), 111 deletions(-) create mode 100644 src/main/kotlin/oap/application/plugin/manipulators/OapParameterKeyValueFirstIdManipulator.kt create mode 100644 src/main/kotlin/oap/application/plugin/psi/impl/JvmNamedElementReference.kt create mode 100644 src/test/kotlin/oap/application/plugin/gotoref/GotoParameterTest.kt diff --git a/build.gradle.kts b/build.gradle.kts index bce483a..ac3e6a0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { } group = "oap" -version = "0.0.5" +version = "0.0.6" repositories { mavenCentral() diff --git a/gen/oap/application/plugin/gen/parser/OapParser.java b/gen/oap/application/plugin/gen/parser/OapParser.java index d2bf3cc..cbe640c 100644 --- a/gen/oap/application/plugin/gen/parser/OapParser.java +++ b/gen/oap/application/plugin/gen/parser/OapParser.java @@ -644,11 +644,9 @@ private static boolean java_parameters_object_2_0_0(PsiBuilder b, int l) { // [] // module_name_pair // ( &'enabled' module_enabled )? - // ( &'include' module_include )* // ( &'dependsOn' module_depends_on )? // ( &'include' module_include )* // ( &'services' module_services )? - // ( &'include' module_include )* // ( &'configurations' module_configurations )? static boolean module(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "module")) return false; @@ -661,9 +659,7 @@ static boolean module(PsiBuilder b, int l) { r = p && report_error_(b, module_3(b, l + 1)) && r; r = p && report_error_(b, module_4(b, l + 1)) && r; r = p && report_error_(b, module_5(b, l + 1)) && r; - r = p && report_error_(b, module_6(b, l + 1)) && r; - r = p && report_error_(b, module_7(b, l + 1)) && r; - r = p && module_8(b, l + 1) && r; + r = p && module_6(b, l + 1) && r; exit_section_(b, l, m, r, p, OapParser::recover_module); return r || p; } @@ -701,179 +697,115 @@ private static boolean module_2_0_0(PsiBuilder b, int l) { return r; } - // ( &'include' module_include )* + // ( &'dependsOn' module_depends_on )? private static boolean module_3(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "module_3")) return false; - while (true) { - int c = current_position_(b); - if (!module_3_0(b, l + 1)) break; - if (!empty_element_parsed_guard_(b, "module_3", c)) break; - } + module_3_0(b, l + 1); return true; } - // &'include' module_include + // &'dependsOn' module_depends_on private static boolean module_3_0(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "module_3_0")) return false; boolean r; Marker m = enter_section_(b); r = module_3_0_0(b, l + 1); - r = r && module_include(b, l + 1); + r = r && module_depends_on(b, l + 1); exit_section_(b, m, null, r); return r; } - // &'include' + // &'dependsOn' private static boolean module_3_0_0(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "module_3_0_0")) return false; boolean r; Marker m = enter_section_(b, l, _AND_); - r = consumeToken(b, OAP_ID_INCLUDE); + r = consumeToken(b, OAP_ID_DEPENDS_ON); exit_section_(b, l, m, r, false, null); return r; } - // ( &'dependsOn' module_depends_on )? + // ( &'include' module_include )* private static boolean module_4(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "module_4")) return false; - module_4_0(b, l + 1); + while (true) { + int c = current_position_(b); + if (!module_4_0(b, l + 1)) break; + if (!empty_element_parsed_guard_(b, "module_4", c)) break; + } return true; } - // &'dependsOn' module_depends_on + // &'include' module_include private static boolean module_4_0(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "module_4_0")) return false; boolean r; Marker m = enter_section_(b); r = module_4_0_0(b, l + 1); - r = r && module_depends_on(b, l + 1); + r = r && module_include(b, l + 1); exit_section_(b, m, null, r); return r; } - // &'dependsOn' + // &'include' private static boolean module_4_0_0(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "module_4_0_0")) return false; boolean r; Marker m = enter_section_(b, l, _AND_); - r = consumeToken(b, OAP_ID_DEPENDS_ON); + r = consumeToken(b, OAP_ID_INCLUDE); exit_section_(b, l, m, r, false, null); return r; } - // ( &'include' module_include )* + // ( &'services' module_services )? private static boolean module_5(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "module_5")) return false; - while (true) { - int c = current_position_(b); - if (!module_5_0(b, l + 1)) break; - if (!empty_element_parsed_guard_(b, "module_5", c)) break; - } + module_5_0(b, l + 1); return true; } - // &'include' module_include + // &'services' module_services private static boolean module_5_0(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "module_5_0")) return false; boolean r; Marker m = enter_section_(b); r = module_5_0_0(b, l + 1); - r = r && module_include(b, l + 1); + r = r && module_services(b, l + 1); exit_section_(b, m, null, r); return r; } - // &'include' + // &'services' private static boolean module_5_0_0(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "module_5_0_0")) return false; boolean r; Marker m = enter_section_(b, l, _AND_); - r = consumeToken(b, OAP_ID_INCLUDE); + r = consumeToken(b, OAP_ID_SERVICES); exit_section_(b, l, m, r, false, null); return r; } - // ( &'services' module_services )? + // ( &'configurations' module_configurations )? private static boolean module_6(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "module_6")) return false; module_6_0(b, l + 1); return true; } - // &'services' module_services + // &'configurations' module_configurations private static boolean module_6_0(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "module_6_0")) return false; boolean r; Marker m = enter_section_(b); r = module_6_0_0(b, l + 1); - r = r && module_services(b, l + 1); - exit_section_(b, m, null, r); - return r; - } - - // &'services' - private static boolean module_6_0_0(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "module_6_0_0")) return false; - boolean r; - Marker m = enter_section_(b, l, _AND_); - r = consumeToken(b, OAP_ID_SERVICES); - exit_section_(b, l, m, r, false, null); - return r; - } - - // ( &'include' module_include )* - private static boolean module_7(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "module_7")) return false; - while (true) { - int c = current_position_(b); - if (!module_7_0(b, l + 1)) break; - if (!empty_element_parsed_guard_(b, "module_7", c)) break; - } - return true; - } - - // &'include' module_include - private static boolean module_7_0(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "module_7_0")) return false; - boolean r; - Marker m = enter_section_(b); - r = module_7_0_0(b, l + 1); - r = r && module_include(b, l + 1); - exit_section_(b, m, null, r); - return r; - } - - // &'include' - private static boolean module_7_0_0(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "module_7_0_0")) return false; - boolean r; - Marker m = enter_section_(b, l, _AND_); - r = consumeToken(b, OAP_ID_INCLUDE); - exit_section_(b, l, m, r, false, null); - return r; - } - - // ( &'configurations' module_configurations )? - private static boolean module_8(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "module_8")) return false; - module_8_0(b, l + 1); - return true; - } - - // &'configurations' module_configurations - private static boolean module_8_0(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "module_8_0")) return false; - boolean r; - Marker m = enter_section_(b); - r = module_8_0_0(b, l + 1); r = r && module_configurations(b, l + 1); exit_section_(b, m, null, r); return r; } // &'configurations' - private static boolean module_8_0_0(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "module_8_0_0")) return false; + private static boolean module_6_0_0(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "module_6_0_0")) return false; boolean r; Marker m = enter_section_(b, l, _AND_); r = consumeToken(b, OAP_ID_CONFIGURATIONS); diff --git a/gen/oap/application/plugin/gen/psi/OapModuleServicesServiceLinkField.java b/gen/oap/application/plugin/gen/psi/OapModuleServicesServiceLinkField.java index 66e29d6..a825bbe 100644 --- a/gen/oap/application/plugin/gen/psi/OapModuleServicesServiceLinkField.java +++ b/gen/oap/application/plugin/gen/psi/OapModuleServicesServiceLinkField.java @@ -4,9 +4,9 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -import oap.application.plugin.psi.OapCompositeElement; +import oap.application.plugin.psi.IndentNormal; -public interface OapModuleServicesServiceLinkField extends OapCompositeElement { +public interface OapModuleServicesServiceLinkField extends IndentNormal { @Nullable OapReferenceModulesValue getReferenceModulesValue(); diff --git a/gen/oap/application/plugin/gen/psi/OapParameterKeyValueFirstId.java b/gen/oap/application/plugin/gen/psi/OapParameterKeyValueFirstId.java index 23ffffe..aa48f06 100644 --- a/gen/oap/application/plugin/gen/psi/OapParameterKeyValueFirstId.java +++ b/gen/oap/application/plugin/gen/psi/OapParameterKeyValueFirstId.java @@ -5,10 +5,13 @@ import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; import oap.application.plugin.psi.OapCompositeElement; +import oap.application.plugin.psi.impl.JvmNamedElementReference; public interface OapParameterKeyValueFirstId extends OapCompositeElement { @NotNull PsiElement getKeyName(); + @Nullable JvmNamedElementReference getReference(); + } diff --git a/gen/oap/application/plugin/gen/psi/OapVisitor.java b/gen/oap/application/plugin/gen/psi/OapVisitor.java index b276d51..89ee6df 100644 --- a/gen/oap/application/plugin/gen/psi/OapVisitor.java +++ b/gen/oap/application/plugin/gen/psi/OapVisitor.java @@ -161,7 +161,7 @@ public void visitModuleServicesServiceLink(@NotNull OapModuleServicesServiceLink } public void visitModuleServicesServiceLinkField(@NotNull OapModuleServicesServiceLinkField o) { - visitCompositeElement(o); + visitIndentNormal(o); } public void visitModuleServicesServiceLinkFieldObject(@NotNull OapModuleServicesServiceLinkFieldObject o) { diff --git a/gen/oap/application/plugin/gen/psi/impl/OapParameterKeyValueFirstIdImpl.java b/gen/oap/application/plugin/gen/psi/impl/OapParameterKeyValueFirstIdImpl.java index 1878f35..2b9803d 100644 --- a/gen/oap/application/plugin/gen/psi/impl/OapParameterKeyValueFirstIdImpl.java +++ b/gen/oap/application/plugin/gen/psi/impl/OapParameterKeyValueFirstIdImpl.java @@ -11,6 +11,7 @@ import oap.application.plugin.psi.impl.OapCompositeElementImpl; import oap.application.plugin.gen.psi.*; import oap.application.plugin.psi.impl.GrammarPsiImplUtil; +import oap.application.plugin.psi.impl.JvmNamedElementReference; public class OapParameterKeyValueFirstIdImpl extends OapCompositeElementImpl implements OapParameterKeyValueFirstId { @@ -34,4 +35,9 @@ public PsiElement getKeyName() { return notNullChild(findChildByType(OAP_KEY_NAME)); } + @Override + public @Nullable JvmNamedElementReference getReference() { + return GrammarPsiImplUtil.getReference(this); + } + } diff --git a/grammars/oap.bnf b/grammars/oap.bnf index d538e7a..41b8cdf 100644 --- a/grammars/oap.bnf +++ b/grammars/oap.bnf @@ -93,11 +93,9 @@ module ::= [] module_name_pair ( &'enabled' module_enabled )? - ( &'include' module_include )* ( &'dependsOn' module_depends_on )? ( &'include' module_include )* ( &'services' module_services )? - ( &'include' module_include )* ( &'configurations' module_configurations )? { pin = 1 recoverWhile=recover_module @@ -269,7 +267,9 @@ parameters_array_item ::= &'<' any_reference | &'{' parameters_object | function java_parameter_key_value ::= parameter_key_value private java_parameters_object ::= '{' java_parameter_key_value? (','? java_parameter_key_value )* '}' {pin=1} -parameter_key_value_first_id ::= key_name +parameter_key_value_first_id ::= key_name { + methods=[getReference] +} parameter_key_value ::= parameter_key_value_first_id ('.' key_name)* (&'=' parameter_key_value_key_eq | parameter_key_value_key_object ) { pin=1 mixin="oap.application.plugin.psi.OapModuleServicesServiceParameterKeyValueMixin" @@ -287,7 +287,10 @@ module_services_service_listen ::= 'listen' ( &'.' dot_module_services_service_l dot_module_services_service_link_field ::= '.' module_services_service_link_field {pin=1} module_services_service_link_field_object ::= '{' module_services_service_link_field* '}' {pin=1} -module_services_service_link_field ::= key_name '=' reference_modules_value {pin=1} +module_services_service_link_field ::= key_name '=' reference_modules_value { + pin=1 + implements="oap.application.plugin.psi.IndentNormal" +} module_services_service_link ::= 'link' ( &'.' dot_module_services_service_link_field | module_services_service_link_field_object ) { pin=1 diff --git a/src/main/kotlin/oap/application/plugin/editor/JavaOapServiceLineMarkerProvider.kt b/src/main/kotlin/oap/application/plugin/editor/JavaOapServiceLineMarkerProvider.kt index 4f234a0..43efcfa 100644 --- a/src/main/kotlin/oap/application/plugin/editor/JavaOapServiceLineMarkerProvider.kt +++ b/src/main/kotlin/oap/application/plugin/editor/JavaOapServiceLineMarkerProvider.kt @@ -26,7 +26,7 @@ class JavaOapServiceLineMarkerProvider : LineMarkerProvider { .setTargets(services) .setTooltipText("Service implementation") .setAlignment(GutterIconRenderer.Alignment.RIGHT) - .createLineMarkerInfo(element) + .createLineMarkerInfo(element.nameIdentifier!!) } } diff --git a/src/main/kotlin/oap/application/plugin/manipulators/OapParameterKeyValueFirstIdManipulator.kt b/src/main/kotlin/oap/application/plugin/manipulators/OapParameterKeyValueFirstIdManipulator.kt new file mode 100644 index 0000000..759bbf9 --- /dev/null +++ b/src/main/kotlin/oap/application/plugin/manipulators/OapParameterKeyValueFirstIdManipulator.kt @@ -0,0 +1,17 @@ +package oap.application.plugin.manipulators + +import com.intellij.openapi.util.TextRange +import com.intellij.psi.AbstractElementManipulator +import oap.application.plugin.gen.psi.OapParameterKeyValueFirstId +import oap.application.plugin.psi.IModuleName +import oap.application.plugin.psi.OapPsiElementFactory + +class OapParameterKeyValueFirstIdManipulator : AbstractElementManipulator() { + override fun handleContentChange( + element: OapParameterKeyValueFirstId, + range: TextRange, + newContent: String + ): OapParameterKeyValueFirstId? { + return OapPsiElementFactory.replaceText(element, newContent); + } +} \ No newline at end of file diff --git a/src/main/kotlin/oap/application/plugin/psi/impl/GrammarPsiImplUtil.kt b/src/main/kotlin/oap/application/plugin/psi/impl/GrammarPsiImplUtil.kt index d2c6d5f..b4423b8 100644 --- a/src/main/kotlin/oap/application/plugin/psi/impl/GrammarPsiImplUtil.kt +++ b/src/main/kotlin/oap/application/plugin/psi/impl/GrammarPsiImplUtil.kt @@ -1,6 +1,11 @@ package oap.application.plugin.psi.impl +import com.intellij.lang.jvm.JvmParameter +import com.intellij.openapi.util.text.Strings +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiField import com.intellij.psi.PsiFile +import com.intellij.psi.PsiMethod import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.stubs.StubIndex import com.intellij.psi.util.PsiTreeUtil @@ -8,6 +13,7 @@ import oap.application.plugin.gen.psi.* import oap.application.plugin.psi.IModuleName import oap.application.plugin.psi.IServiceName import oap.application.plugin.psi.ModuleUtils +import oap.application.plugin.psi.OapClassValueMixin import oap.application.plugin.stub.OapModuleNameIndex class GrammarPsiImplUtil { @@ -61,5 +67,33 @@ class GrammarPsiImplUtil { return service?.let { OapServiceReference(m, it) } } + + @JvmStatic + fun getReference(m: OapParameterKeyValueFirstId): JvmNamedElementReference? { + val service: OapModuleServicesService? = PsiTreeUtil.getParentOfType(m, OapModuleServicesService::class.java) + val psiClass: PsiClass? = (service?.moduleServicesServiceImplementation?.classNamePsi as? OapClassValueMixin)?.getPsiClass() + + if (psiClass != null) { + val propertyName: String = m.keyName.text + + val psiMethod: PsiMethod? = psiClass.methods.firstOrNull { m -> m.name.startsWith("set" + Strings.capitalize(propertyName)) && m.parameterList.parametersCount == 1 } + if (psiMethod != null) { + return JvmNamedElementReference(m, psiMethod) + } + + val parameter: JvmParameter? = psiClass.constructors.flatMap { c -> c.parameters.filter { p -> propertyName.equals(p.name) } }.firstOrNull() + if (parameter != null) { + return JvmNamedElementReference(m, parameter); + } + + val psiField: PsiField? = psiClass.allFields.firstOrNull { it.name.equals(propertyName) } + + if (psiField != null) { + return JvmNamedElementReference(m, psiField) + } + } + + return null; + } } } \ No newline at end of file diff --git a/src/main/kotlin/oap/application/plugin/psi/impl/JvmNamedElementReference.kt b/src/main/kotlin/oap/application/plugin/psi/impl/JvmNamedElementReference.kt new file mode 100644 index 0000000..019377b --- /dev/null +++ b/src/main/kotlin/oap/application/plugin/psi/impl/JvmNamedElementReference.kt @@ -0,0 +1,11 @@ +package oap.application.plugin.psi.impl + +import com.intellij.lang.jvm.JvmNamedElement +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiReferenceBase + +class JvmNamedElementReference(owner: PsiElement, val javaElement: JvmNamedElement) : PsiReferenceBase(owner) { + override fun resolve(): PsiElement { + return javaElement.sourceElement!! + } +} \ No newline at end of file diff --git a/src/main/kotlin/oap/application/plugin/ref/ValidParametersInspection.kt b/src/main/kotlin/oap/application/plugin/ref/ValidParametersInspection.kt index f1d0a64..dfd2f61 100644 --- a/src/main/kotlin/oap/application/plugin/ref/ValidParametersInspection.kt +++ b/src/main/kotlin/oap/application/plugin/ref/ValidParametersInspection.kt @@ -3,6 +3,7 @@ package oap.application.plugin.ref import com.intellij.codeInspection.LocalInspectionTool import com.intellij.codeInspection.ProblemHighlightType import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.util.NlsSafe import com.intellij.openapi.util.text.Strings import com.intellij.psi.* import com.intellij.psi.util.PsiTreeUtil @@ -21,19 +22,18 @@ class ValidParametersInspection : LocalInspectionTool() { val psiClass: PsiClass? = (service?.moduleServicesServiceImplementation?.classNamePsi as? OapClassValueMixin)?.getPsiClass() if (psiClass != null) { val firstId: OapParameterKeyValueFirstId? = PsiTreeUtil.findChildOfType(element, OapParameterKeyValueFirstId::class.java) - val propertyName: String? = firstId?.keyName?.text - if (propertyName == null) { - return; - } - val setter: Boolean = psiClass.methods.firstOrNull { m -> m.name.startsWith("set" + Strings.capitalize(propertyName)) && m.parameterList.parametersCount == 1 } == null + + val propertyName: String = firstId?.keyName?.text ?: return + + val setter: Boolean = psiClass.methods.firstOrNull { it.name.startsWith("set" + Strings.capitalize(propertyName)) && it.parameterList.parametersCount == 1 } == null if (!setter) { return; } - val parameter: Boolean = psiClass.constructors.flatMap { c -> c.parameters.mapNotNull { p -> p.name } }.distinct().contains(propertyName) + val parameter: Boolean = psiClass.constructors.flatMap { it.parameters.mapNotNull { it.name } }.distinct().contains(propertyName) if (parameter) { return; } - val psiField: PsiField? = psiClass.allFields.firstOrNull { f -> f.name.equals(propertyName) } + val psiField: PsiField? = psiClass.allFields.firstOrNull { it.name.equals(propertyName) } if (psiField == null) { holder.registerProblem( firstId, diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 9752b92..4a01865 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -56,6 +56,8 @@ implementationClass="oap.application.plugin.manipulators.OapModuleNameManipulator"/> + diff --git a/src/test/kotlin/oap/application/plugin/gotoref/GotoParameterTest.kt b/src/test/kotlin/oap/application/plugin/gotoref/GotoParameterTest.kt new file mode 100644 index 0000000..9d48cb8 --- /dev/null +++ b/src/test/kotlin/oap/application/plugin/gotoref/GotoParameterTest.kt @@ -0,0 +1,45 @@ +package oap.application.plugin.gotoref + +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiField +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiParameter +import com.intellij.psi.PsiReference +import oap.application.plugin.OapFixtureTestCase +import oap.application.plugin.gen.psi.OapModuleServicesService +import org.assertj.core.api.Assertions +import org.assertj.core.api.Assertions.assertThat +import java.io.File + +class GotoParameterTest : OapFixtureTestCase() { + override fun getTestDataPath(): String { + return File("src/test/java").absolutePath + } + + fun testGotoField() { + val javaFile: PsiFile = myFixture.configureByFile("oap/application/plugin/TestJavaService.java") + + val file: PsiFile = myFixture.configureByText( + "testParameterAsField.oap", """ + name = testParameterAsField + services { + testParameterAsField { + implementation = oap.application.plugin.TestJavaService + parameters { + stringField = "dfg" + } + } + } + """.trimIndent() + ) + + myFixture.openFileInEditor(file.virtualFile) + + val focusedElement: PsiElement = myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset())!! + val reference: PsiReference? = focusedElement.reference ?: focusedElement.parent.reference + + val psiElement: PsiElement? = reference?.resolve() + assertThat(psiElement).isInstanceOf(PsiField::class.java) + assertThat(psiElement?.containingFile).isSameAs(javaFile) + } +} \ No newline at end of file