mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
groovy: generated constructors should have some types on parameters (IDEA-56826) and their bodies should not have semicolons (IDEA-27066)
This commit is contained in:
@@ -48,6 +48,7 @@ public class LightVariableBuilder extends LightElement implements PsiVariable {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiModifierList getModifierList() {
|
||||
return myModifierList;
|
||||
}
|
||||
|
||||
+33
-30
@@ -17,12 +17,16 @@ package org.jetbrains.plugins.groovy.actions.generate.constructors;
|
||||
|
||||
import com.intellij.codeInsight.generation.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.compiler.generator.GroovyToJavaGenerator;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
|
||||
@@ -35,55 +39,50 @@ import java.util.List;
|
||||
*/
|
||||
public class ConstructorGenerateHandler extends GenerateConstructorHandler {
|
||||
|
||||
private static final String DEF_PSEUDO_ANNO = "_____intellij_idea_rulez_def_";
|
||||
|
||||
@Nullable
|
||||
protected ClassMember[] chooseOriginalMembers(PsiClass aClass, Project project) {
|
||||
final ClassMember[] classMembers = super.chooseOriginalMembers(aClass, project);
|
||||
|
||||
final ClassMember[] classMembers = chooseOriginalMembersImpl(aClass, project);
|
||||
if (classMembers == null) return null;
|
||||
|
||||
List<ClassMember> res = new ArrayList<ClassMember>();
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory();
|
||||
String text;
|
||||
|
||||
for (ClassMember classMember : classMembers) {
|
||||
|
||||
if (classMember instanceof PsiMethodMember) {
|
||||
PsiMethod constructorImpl;
|
||||
final PsiMethod method = ((PsiMethodMember) classMember).getElement();
|
||||
|
||||
//TODO: rewrite it like fine java method
|
||||
text = method.getText();
|
||||
try {
|
||||
constructorImpl = factory.createMethodFromText(text, aClass);
|
||||
res.add(new PsiMethodMember(constructorImpl));
|
||||
} catch (IncorrectOperationException e) {
|
||||
e.printStackTrace();
|
||||
final PsiMethod method = ((PsiMethodMember)classMember).getElement();
|
||||
final PsiMethod copy = (PsiMethod)method.copy();
|
||||
if (copy instanceof GrMethod) {
|
||||
for (GrParameter parameter : ((GrMethod)copy).getParameterList().getParameters()) {
|
||||
if (parameter.getTypeElementGroovy() == null) {
|
||||
parameter.setName(DEF_PSEUDO_ANNO + parameter.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.add(new PsiMethodMember(factory.createMethodFromText(GroovyToJavaGenerator.generateMethodStub(copy), aClass)));
|
||||
} else if (classMember instanceof PsiFieldMember) {
|
||||
final PsiFieldMember fieldMember = (PsiFieldMember) classMember;
|
||||
PsiField fieldImpl;
|
||||
final PsiField field = ((PsiFieldMember) classMember).getElement();
|
||||
|
||||
final PsiField field = fieldMember.getElement();
|
||||
try {
|
||||
fieldImpl = factory.createFieldFromText(field.getType().getCanonicalText() + " " + field.getName(), aClass);
|
||||
res.add(new PsiFieldMember(fieldImpl));
|
||||
} catch (IncorrectOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
String prefix = field instanceof GrField && ((GrField)field).getTypeElementGroovy() == null ? DEF_PSEUDO_ANNO : "";
|
||||
res.add(new PsiFieldMember(factory.createFieldFromText(field.getType().getCanonicalText() + " " + prefix + field.getName(), aClass)));
|
||||
}
|
||||
}
|
||||
|
||||
return res.toArray(new ClassMember[res.size()]);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ClassMember[] chooseOriginalMembersImpl(PsiClass aClass, Project project) {
|
||||
return super.chooseOriginalMembers(aClass, project);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected List<? extends GenerationInfo> generateMemberPrototypes(PsiClass aClass, ClassMember[] members) throws IncorrectOperationException {
|
||||
final List<? extends GenerationInfo> list = super.generateMemberPrototypes(aClass, members);
|
||||
|
||||
List<PsiGenerationInfo<GrMethod>> grConstructors = new ArrayList<PsiGenerationInfo<GrMethod>>();
|
||||
|
||||
GrMethod grConstructor;
|
||||
for (GenerationInfo generationInfo : list) {
|
||||
final PsiMember constructorMember = generationInfo.getPsiMember();
|
||||
assert constructorMember instanceof PsiMethod;
|
||||
@@ -93,22 +92,26 @@ public class ConstructorGenerateHandler extends GenerateConstructorHandler {
|
||||
assert block != null;
|
||||
|
||||
final String constructorName = aClass.getName();
|
||||
final String body = block.getText();
|
||||
final String body = StringUtil.replace(StringUtil.replace(block.getText(), DEF_PSEUDO_ANNO, ""), ";", "");
|
||||
final PsiParameterList list1 = constructor.getParameterList();
|
||||
|
||||
List<String> parametersNames = new ArrayList<String>();
|
||||
List<String> parametersTypes = new ArrayList<String>();
|
||||
for (PsiParameter parameter : list1.getParameters()) {
|
||||
parametersNames.add(parameter.getName());
|
||||
final String fullName = parameter.getName();
|
||||
parametersNames.add(StringUtil.trimStart(fullName, DEF_PSEUDO_ANNO));
|
||||
parametersTypes.add(fullName.startsWith(DEF_PSEUDO_ANNO) ? null : parameter.getType().getCanonicalText());
|
||||
}
|
||||
|
||||
final String[] paramNames = ArrayUtil.toStringArray(parametersNames);
|
||||
final String[] paramTypes = ArrayUtil.toStringArray(parametersTypes);
|
||||
assert constructorName != null;
|
||||
grConstructor = GroovyPsiElementFactory.getInstance(aClass.getProject()).createConstructorFromText(constructorName, null, paramNames, body);
|
||||
GrMethod grConstructor =
|
||||
GroovyPsiElementFactory.getInstance(aClass.getProject()).createConstructorFromText(constructorName, paramTypes, paramNames, body);
|
||||
|
||||
PsiUtil.shortenReferences(grConstructor);
|
||||
|
||||
final PsiGenerationInfo<GrMethod> psiGenerationInfo = new GroovyGenerationInfo<GrMethod>(grConstructor);
|
||||
grConstructors.add(psiGenerationInfo);
|
||||
grConstructors.add(new GroovyGenerationInfo<GrMethod>(grConstructor));
|
||||
}
|
||||
|
||||
return grConstructors;
|
||||
|
||||
+17
@@ -50,6 +50,7 @@ import org.jetbrains.plugins.groovy.compiler.GroovyCompilerConfiguration;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrClassSubstitutor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
|
||||
@@ -697,6 +698,22 @@ public class GroovyToJavaGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
public static String generateMethodStub(@NotNull PsiMethod method) {
|
||||
if (!(method instanceof GroovyPsiElement)) {
|
||||
return method.getText();
|
||||
}
|
||||
|
||||
final GroovyToJavaGenerator generator = new GroovyToJavaGenerator(method.getProject(), null, Collections.<VirtualFile>emptyList());
|
||||
final StringBuffer buffer = new StringBuffer();
|
||||
if (method instanceof GrConstructor) {
|
||||
generator.writeConstructor(buffer, (GrConstructor)method, false);
|
||||
}
|
||||
else {
|
||||
generator.writeMethod(buffer, method, method.getParameterList().getParameters());
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private void writeMethod(StringBuffer text, PsiMethod method, final PsiParameter[] parameters) {
|
||||
if (method == null) return;
|
||||
String name = method.getName();
|
||||
|
||||
+5
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.lang.psi.api.statements.params;
|
||||
|
||||
import com.intellij.psi.PsiModifierList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
@@ -35,5 +37,8 @@ public interface GrParameter extends PsiParameter, GrVariable {
|
||||
@Nullable
|
||||
GrExpression getDefaultInitializer();
|
||||
|
||||
@NotNull
|
||||
PsiModifierList getModifierList();
|
||||
|
||||
boolean isOptional();
|
||||
}
|
||||
|
||||
+5
-3
@@ -528,12 +528,14 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
|
||||
builder.append("(");
|
||||
|
||||
for (int i = 0; i < paramNames.length; i++) {
|
||||
String paramType = paramTypes == null ? "" : paramTypes[i];
|
||||
String paramType = paramTypes == null ? null : paramTypes[i];
|
||||
|
||||
if (i > 0) builder.append(", ");
|
||||
|
||||
builder.append(paramType);
|
||||
builder.append(" ");
|
||||
if (paramType != null) {
|
||||
builder.append(paramType);
|
||||
builder.append(" ");
|
||||
}
|
||||
builder.append(paramNames[i]);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -185,9 +185,9 @@ public class GrParameterImpl extends GrVariableImpl implements GrParameter {
|
||||
return getNameIdentifierGroovy().getTextRange().getStartOffset();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
public GrModifierList getModifierList() {
|
||||
return findChildByClass(GrModifierList.class);
|
||||
return findNotNullChildByClass(GrModifierList.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+2
-1
@@ -27,6 +27,7 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -314,7 +315,7 @@ public class GroovyOverrideImplementUtil {
|
||||
JavaTemplateUtil.setClassAndMethodNameProperties(properties, method.getContainingClass(), resultMethod);
|
||||
|
||||
try {
|
||||
String bodyText = template.getText(properties);
|
||||
String bodyText = StringUtil.replace(template.getText(properties), ";", "");
|
||||
final GrCodeBlock newBody = GroovyPsiElementFactory.getInstance(project).createMethodBodyFromText("\n" + bodyText + "\n");
|
||||
|
||||
resultMethod.setBlock(newBody);
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.actions.generate;
|
||||
|
||||
|
||||
import com.intellij.codeInsight.generation.ClassMember
|
||||
import com.intellij.codeInsight.generation.PsiFieldMember
|
||||
import com.intellij.openapi.application.Result
|
||||
import com.intellij.openapi.application.RunResult
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.plugins.groovy.actions.generate.constructors.ConstructorGenerateHandler
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils
|
||||
import com.intellij.codeInsight.generation.PsiMethodMember
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class GroovyGenerateMembersTest extends LightCodeInsightFixtureTestCase {
|
||||
|
||||
public void testConstructorAtOffset() throws Throwable {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testConstructorAtEnd() throws Throwable {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testLonelyConstructor() throws Throwable {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testExplicitArgumentTypes() throws Exception {
|
||||
myFixture.configureByText("a.groovy", """
|
||||
class Super {
|
||||
def Super(a, int b) {}
|
||||
}
|
||||
|
||||
class Foo extends Super {
|
||||
int c
|
||||
Object d
|
||||
final e
|
||||
<caret>
|
||||
}
|
||||
""")
|
||||
generateConstructor()
|
||||
myFixture.checkResult """
|
||||
class Super {
|
||||
def Super(a, int b) {}
|
||||
}
|
||||
|
||||
class Foo extends Super {
|
||||
int c
|
||||
Object d
|
||||
final e
|
||||
|
||||
def Foo(a, int b, int c, Object d, e) {
|
||||
super(a, b)
|
||||
this.c = c
|
||||
this.d = d
|
||||
this.e = e
|
||||
}
|
||||
}
|
||||
"""
|
||||
}
|
||||
|
||||
private void doTest() throws Throwable {
|
||||
myFixture.configureByFile(getTestName(false) + ".groovy");
|
||||
generateConstructor();
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.groovy");
|
||||
}
|
||||
|
||||
RunResult generateConstructor() {
|
||||
return new WriteCommandAction(getProject(), new PsiFile[0]) {
|
||||
protected void run(Result result) throws Throwable {
|
||||
new ConstructorGenerateHandler() {
|
||||
@Override protected ClassMember[] chooseOriginalMembersImpl(PsiClass aClass, Project project) {
|
||||
List<ClassMember> members = aClass.fields.collect { new PsiFieldMember(it) }
|
||||
members << new PsiMethodMember(aClass.superClass.constructors[0])
|
||||
return members as ClassMember[]
|
||||
}
|
||||
|
||||
}.invoke(getProject(), myFixture.getEditor(), myFixture.getFile());
|
||||
}
|
||||
}.execute()
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return TestUtils.getTestDataPath() + "generate";
|
||||
}
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.actions.generate;
|
||||
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.plugins.groovy.actions.generate.constructors.ConstructorGenerateHandler;
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class GroovyGenerateMembersTest extends LightCodeInsightFixtureTestCase {
|
||||
|
||||
public void testConstructorAtOffset() throws Throwable {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testConstructorAtEnd() throws Throwable {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testLonelyConstructor() throws Throwable {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() throws Throwable {
|
||||
myFixture.configureByFile(getTestName(false) + ".groovy");
|
||||
new WriteCommandAction(getProject()) {
|
||||
protected void run(Result result) throws Throwable {
|
||||
new ConstructorGenerateHandler().invoke(getProject(), myFixture.getEditor(), myFixture.getFile());
|
||||
}
|
||||
}.execute();
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.groovy");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return TestUtils.getTestDataPath() + "generate";
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -24,7 +24,7 @@ class Test {<caret>}
|
||||
class Test {
|
||||
@Override
|
||||
boolean equals(Object obj) {
|
||||
return super.equals(obj); //To change body of overridden methods use File | Settings | File Templates.
|
||||
return super.equals(obj) //To change body of overridden methods use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
"""
|
||||
@@ -38,7 +38,7 @@ class Test {<caret>}
|
||||
myFixture.checkResult """
|
||||
class Test {
|
||||
def Test() {
|
||||
super(); //To change body of overridden methods use File | Settings | File Templates.
|
||||
super() //To change body of overridden methods use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
"""
|
||||
@@ -59,7 +59,7 @@ class Test {<caret>}
|
||||
myFixture.checkResult """
|
||||
class Test {
|
||||
@Override def foo() {
|
||||
return super.foo(); //To change body of overridden methods use File | Settings | File Templates.
|
||||
return super.foo() //To change body of overridden methods use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user