mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[groovy] add support for Geb content definition based methods
This commit is contained in:
committed by
Daniil Ovchinnikov
parent
6d0dde7eaf
commit
ee1b8df58d
+6
-20
@@ -1,25 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.geb;
|
||||
|
||||
import com.intellij.pom.PomDeclarationSearcher;
|
||||
import com.intellij.pom.PomTarget;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
@@ -52,11 +38,11 @@ public class GebContentDeclarationSearcher extends PomDeclarationSearcher {
|
||||
if (!InheritanceUtil.isInheritor(containingClass, "geb.Page")
|
||||
&& !InheritanceUtil.isInheritor(containingClass, "geb.Module")) return;
|
||||
|
||||
Map<String, PsiField> elements = GebUtil.getContentElements(containingClass);
|
||||
Map<String, PsiMember> contentElements = GebUtil.getContentElements(containingClass);
|
||||
|
||||
for (PsiField f : elements.values()) {
|
||||
if (f.getNavigationElement() == element) {
|
||||
consumer.consume(f);
|
||||
for (PsiMember contentElement : contentElements.values()) {
|
||||
if (contentElement.getNavigationElement() == element) {
|
||||
consumer.consume(contentElement);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-28
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.geb;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
@@ -54,10 +40,10 @@ public class GebPageMemberContributor extends NonCodeMembersContributor {
|
||||
if (contentField instanceof GrField) {
|
||||
GrField f = (GrField)contentField;
|
||||
if ("content".equals(f.getName()) && f.hasModifierProperty(PsiModifier.STATIC) && f.getContainingClass() == aClass) {
|
||||
Map<String, PsiField> elements = GebUtil.getContentElements(aClass);
|
||||
for (PsiField field : elements.values()) {
|
||||
if (field.getNavigationElement() == place) {
|
||||
return; // Don't resolve variable definition.
|
||||
Map<String, PsiMember> elements = GebUtil.getContentElements(aClass);
|
||||
for (PsiMember element : elements.values()) {
|
||||
if (element.getNavigationElement() == place) {
|
||||
return; // Don't resolve definition.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,27 +51,27 @@ public class GebPageMemberContributor extends NonCodeMembersContributor {
|
||||
}
|
||||
}
|
||||
|
||||
processPageFields(processor, aClass, state);
|
||||
processPageElements(processor, aClass, state);
|
||||
}
|
||||
|
||||
public static boolean processPageFields(PsiScopeProcessor processor,
|
||||
@NotNull PsiClass pageClass,
|
||||
ResolveState state) {
|
||||
public static boolean processPageElements(PsiScopeProcessor processor,
|
||||
@NotNull PsiClass pageClass,
|
||||
ResolveState state) {
|
||||
Map<String, PsiClass> supers = ClassUtil.getSuperClassesWithCache(pageClass);
|
||||
String nameHint = ResolveUtil.getNameHint(processor);
|
||||
|
||||
for (PsiClass psiClass : supers.values()) {
|
||||
Map<String, PsiField> contentFields = GebUtil.getContentElements(psiClass);
|
||||
Map<String, PsiMember> contentElements = GebUtil.getContentElements(psiClass);
|
||||
|
||||
if (nameHint == null) {
|
||||
for (Map.Entry<String, PsiField> entry : contentFields.entrySet()) {
|
||||
for (Map.Entry<String, PsiMember> entry : contentElements.entrySet()) {
|
||||
if (!processor.execute(entry.getValue(), state)) return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiField field = contentFields.get(nameHint);
|
||||
if (field != null) {
|
||||
return processor.execute(field, state);
|
||||
PsiMember element = contentElements.get(nameHint);
|
||||
if (element != null) {
|
||||
return processor.execute(element, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.geb;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
@@ -25,7 +11,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.util.LightCacheKey;
|
||||
|
||||
@@ -38,7 +26,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class GebUtil {
|
||||
|
||||
private static final LightCacheKey<Map<String, PsiField>> KEY = LightCacheKey.createByFileModificationCount();
|
||||
private static final LightCacheKey<Map<String, PsiMember>> KEY = LightCacheKey.createByFileModificationCount();
|
||||
|
||||
public static boolean contributeMembersInsideTest(PsiScopeProcessor processor,
|
||||
PsiElement place,
|
||||
@@ -59,8 +47,8 @@ public class GebUtil {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Map<String, PsiField> getContentElements(@NotNull PsiClass pageOrModuleClass) {
|
||||
Map<String, PsiField> res = KEY.getCachedValue(pageOrModuleClass);
|
||||
public static Map<String, PsiMember> getContentElements(@NotNull PsiClass pageOrModuleClass) {
|
||||
Map<String, PsiMember> res = KEY.getCachedValue(pageOrModuleClass);
|
||||
if (res == null) {
|
||||
res = calculateContentElements(pageOrModuleClass);
|
||||
res = KEY.putCachedValue(pageOrModuleClass, res);
|
||||
@@ -69,7 +57,7 @@ public class GebUtil {
|
||||
return res;
|
||||
}
|
||||
|
||||
private static Map<String, PsiField> calculateContentElements(@NotNull PsiClass pageOrModuleClass) {
|
||||
private static Map<String, PsiMember> calculateContentElements(@NotNull PsiClass pageOrModuleClass) {
|
||||
PsiField contentField = pageOrModuleClass.findFieldByName("content", false);
|
||||
|
||||
if (!(contentField instanceof GrField)) return Collections.emptyMap();
|
||||
@@ -77,7 +65,7 @@ public class GebUtil {
|
||||
GrExpression initializer = ((GrField)contentField).getInitializerGroovy();
|
||||
if (!(initializer instanceof GrClosableBlock)) return Collections.emptyMap();
|
||||
|
||||
Map<String, PsiField> res = new HashMap<>();
|
||||
Map<String, PsiMember> res = new HashMap<>();
|
||||
PsiType objectType = PsiType.getJavaLangObject(pageOrModuleClass.getManager(), pageOrModuleClass.getResolveScope());
|
||||
|
||||
for (PsiElement e = initializer.getFirstChild(); e != null; e = e.getNextSibling()) {
|
||||
@@ -87,6 +75,8 @@ public class GebUtil {
|
||||
GrExpression invokedExpression = methodCall.getInvokedExpression();
|
||||
if (!(invokedExpression instanceof GrReferenceExpression)) continue;
|
||||
if (((GrReferenceExpression)invokedExpression).isQualified()) continue;
|
||||
String name = ((GrReferenceExpression)invokedExpression).getReferenceName();
|
||||
if (name == null) continue;
|
||||
|
||||
GrExpression[] arguments = PsiUtil.getAllArguments((GrCall)e);
|
||||
if (arguments.length == 0) continue;
|
||||
@@ -102,24 +92,58 @@ public class GebUtil {
|
||||
continue;
|
||||
}
|
||||
|
||||
GrLightField field = new GrLightField(pageOrModuleClass, ((GrReferenceExpression)invokedExpression).getReferenceName(), objectType, invokedExpression) {
|
||||
@Override
|
||||
public PsiType getTypeGroovy() {
|
||||
return block.getReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType getDeclaredType() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
field.getModifierList().addModifier(GrModifierFlags.STATIC_MASK);
|
||||
|
||||
res.put(field.getName(), field);
|
||||
PsiMember target;
|
||||
if (block.hasParametersSection()) {
|
||||
target = extractMethodForContent(pageOrModuleClass, name, invokedExpression, block);
|
||||
}
|
||||
else {
|
||||
target = extractFieldForContent(pageOrModuleClass, objectType, name, invokedExpression, block);
|
||||
}
|
||||
res.put(name, target);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiField extractFieldForContent(@NotNull PsiClass pageOrModuleClass,
|
||||
@NotNull PsiType objectType, String name,
|
||||
@NotNull GrExpression invokedExpression,
|
||||
@NotNull GrClosableBlock block) {
|
||||
GrLightField field = new GrLightField(pageOrModuleClass, name, objectType, invokedExpression) {
|
||||
|
||||
@Override
|
||||
public PsiType getTypeGroovy() {
|
||||
return block.getReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType getDeclaredType() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
field.getModifierList().addModifier(GrModifierFlags.STATIC_MASK);
|
||||
return field;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiMethod extractMethodForContent(@NotNull PsiClass pageOrModuleClass,
|
||||
@NotNull String name,
|
||||
@NotNull GrExpression invokedExpression,
|
||||
@NotNull GrClosableBlock block) {
|
||||
GrLightMethodBuilder method = new GrLightMethodBuilder(pageOrModuleClass.getManager(), name) {
|
||||
@Override
|
||||
public PsiType getReturnType() {
|
||||
return block.getReturnType();
|
||||
}
|
||||
};
|
||||
method.setContainingClass(pageOrModuleClass);
|
||||
method.addModifier(GrModifierFlags.STATIC_MASK);
|
||||
method.setNavigationElement(invokedExpression);
|
||||
for (GrParameter parameter : block.getAllParameters()) {
|
||||
method.addParameter(parameter);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.geb
|
||||
|
||||
import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection
|
||||
@@ -92,6 +78,39 @@ class ParentClass extends geb.Page {
|
||||
TestUtils.checkCompletionContains(myFixture, "allElements()", "add()", "firstElement()")
|
||||
}
|
||||
|
||||
void testResolveContentFieldsAndMethods() {
|
||||
myFixture.configureByText("PageWithContent.groovy", """
|
||||
class PageWithContent extends geb.Page {
|
||||
static content = {
|
||||
button { \$('button') }
|
||||
formField { String name -> \$('input', name: name) }
|
||||
}
|
||||
|
||||
def someMethod() {
|
||||
<caret>
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
TestUtils.checkCompletionContains(myFixture, "button", "formField()")
|
||||
}
|
||||
|
||||
void testContentMethodReturnType() {
|
||||
myFixture.configureByText("PageWithContent.groovy", """
|
||||
class PageWithContent extends geb.Page {
|
||||
static content = {
|
||||
formField { String name -> \$('input', name: name) }
|
||||
}
|
||||
|
||||
def someMethod() {
|
||||
formField('username').<caret>
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
TestUtils.checkCompletionContains(myFixture, "allElements()", "add()", "firstElement()")
|
||||
}
|
||||
|
||||
void testCheckHighlighting() {
|
||||
myFixture.enableInspections(GroovyAssignabilityCheckInspection)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user