mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
IDEA-79715 Groovy: Inspection "There is no default constructor available in class *" must have a quickfix
This commit is contained in:
+16
-20
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightUtilBase;
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.generation.ConstructorBodyGenerator;
|
||||
import com.intellij.codeInsight.generation.GenerateMembersUtil;
|
||||
import com.intellij.codeInsight.generation.PsiMethodMember;
|
||||
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
|
||||
@@ -27,6 +28,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
@@ -34,7 +36,6 @@ import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -101,7 +102,7 @@ public class CreateConstructorMatchingSuperFix extends BaseIntentionAction {
|
||||
MemberChooser<PsiMethodMember> chooser = new MemberChooser<PsiMethodMember>(constructors, false, true, project);
|
||||
chooser.setTitle(QuickFixBundle.message("super.class.constructors.chooser.title"));
|
||||
chooser.show();
|
||||
if (chooser.getExitCode() != MemberChooser.OK_EXIT_CODE) return;
|
||||
if (chooser.getExitCode() != DialogWrapper.OK_EXIT_CODE) return;
|
||||
constructors = chooser.getSelectedElements(new PsiMethodMember[0]);
|
||||
isCopyJavadoc = chooser.isCopyJavadoc();
|
||||
}
|
||||
@@ -117,12 +118,12 @@ public class CreateConstructorMatchingSuperFix extends BaseIntentionAction {
|
||||
PsiClass psiClass = JavaPsiFacade.getInstance(targetClass.getProject()).getElementFactory().createClass("X");
|
||||
targetClass.addRangeAfter(psiClass.getLBrace(), psiClass.getRBrace(), targetClass.getLastChild());
|
||||
}
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
|
||||
CodeStyleManager reformatter = CodeStyleManager.getInstance(project);
|
||||
JVMElementFactory factory = JVMElementFactories.getFactory(targetClass.getLanguage(), project);
|
||||
CodeStyleManager formatter = CodeStyleManager.getInstance(project);
|
||||
PsiMethod derived = null;
|
||||
for (PsiMethodMember candidate : constructors1) {
|
||||
PsiMethod base = candidate.getElement();
|
||||
derived = GenerateMembersUtil.substituteGenericMethod(base, candidate.getSubstitutor());
|
||||
derived = GenerateMembersUtil.substituteGenericMethod(base, candidate.getSubstitutor(), targetClass);
|
||||
|
||||
if (!isCopyJavadoc1) {
|
||||
final PsiDocComment docComment = derived.getDocComment();
|
||||
@@ -131,23 +132,18 @@ public class CreateConstructorMatchingSuperFix extends BaseIntentionAction {
|
||||
}
|
||||
}
|
||||
|
||||
final PsiIdentifier identifier = targetClass.getNameIdentifier();
|
||||
LOG.assertTrue(identifier != null, targetClass);
|
||||
derived.getNameIdentifier().replace(identifier);
|
||||
@NonNls StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("void foo () {\nsuper(");
|
||||
derived.setName(targetClass.getName());
|
||||
|
||||
PsiParameter[] params = derived.getParameterList().getParameters();
|
||||
for (int j = 0; j < params.length; j++) {
|
||||
PsiParameter param = params[j];
|
||||
buffer.append(param.getName());
|
||||
if (j < params.length - 1) buffer.append(",");
|
||||
ConstructorBodyGenerator generator = ConstructorBodyGenerator.INSTANCE.forLanguage(derived.getLanguage());
|
||||
if (generator != null) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
generator.start(buffer, derived.getName(), PsiParameter.EMPTY_ARRAY);
|
||||
generator.generateSuperCallIfNeeded(buffer, derived.getParameterList().getParameters());
|
||||
generator.finish(buffer);
|
||||
PsiMethod stub = factory.createMethodFromText(buffer.toString(), targetClass);
|
||||
derived.getBody().replace(stub.getBody());
|
||||
}
|
||||
buffer.append(");\n}");
|
||||
PsiMethod stub = factory.createMethodFromText(buffer.toString(), targetClass);
|
||||
|
||||
derived.getBody().replace(stub.getBody());
|
||||
derived = (PsiMethod)reformatter.reformat(derived);
|
||||
derived = (PsiMethod)formatter.reformat(derived);
|
||||
derived = (PsiMethod)JavaCodeStyleManager.getInstance(project).shortenClassReferences(derived);
|
||||
derived = (PsiMethod)GenerateMembersUtil.insert(targetClass, derived, null, true);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.codeInsight.generation;
|
||||
|
||||
import com.intellij.lang.LanguageExtension;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public interface ConstructorBodyGenerator {
|
||||
LanguageExtension<ConstructorBodyGenerator> INSTANCE = new LanguageExtension<ConstructorBodyGenerator>("com.intellij.constructorBodyGenerator");
|
||||
|
||||
void generateFieldInitialization(@NotNull StringBuilder buffer, @NotNull PsiField[] fields, @NotNull PsiParameter[] parameters);
|
||||
|
||||
void generateSuperCallIfNeeded(@NotNull StringBuilder buffer, @NotNull PsiParameter[] parameters);
|
||||
|
||||
StringBuilder start(StringBuilder buffer, @NotNull String name, @NotNull PsiParameter[] parameters);
|
||||
|
||||
void finish(StringBuilder builder);
|
||||
}
|
||||
+34
-26
@@ -211,7 +211,7 @@ public class GenerateConstructorHandler extends GenerateMembersHandlerBase {
|
||||
|
||||
public static PsiMethod generateConstructorPrototype(PsiClass aClass, PsiMethod baseConstructor, boolean copyJavaDoc, PsiField[] fields) throws IncorrectOperationException {
|
||||
PsiManager manager = aClass.getManager();
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
|
||||
JVMElementFactory factory = JVMElementFactories.getFactory(aClass.getLanguage(), aClass.getProject());
|
||||
CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject());
|
||||
|
||||
PsiMethod constructor = factory.createConstructor();
|
||||
@@ -235,37 +235,28 @@ public class GenerateConstructorHandler extends GenerateMembersHandlerBase {
|
||||
}
|
||||
}
|
||||
|
||||
@NonNls StringBuilder body = new StringBuilder();
|
||||
body.append("{\n");
|
||||
|
||||
boolean isNotEnum = false;
|
||||
if (baseConstructor != null){
|
||||
PsiClass superClass = aClass.getSuperClass();
|
||||
LOG.assertTrue(superClass != null);
|
||||
if (!CommonClassNames.JAVA_LANG_ENUM.equals(superClass.getQualifiedName())) {
|
||||
isNotEnum = true;
|
||||
if (baseConstructor instanceof PsiCompiledElement){ // to get some parameter names
|
||||
PsiClass dummyClass = factory.createClass("Dummy");
|
||||
PsiClass dummyClass = JVMElementFactories.getFactory(baseConstructor.getLanguage(), baseConstructor.getProject()).createClass("Dummy");
|
||||
baseConstructor = (PsiMethod)dummyClass.add(baseConstructor);
|
||||
}
|
||||
PsiParameter[] parms = baseConstructor.getParameterList().getParameters();
|
||||
for (PsiParameter parm : parms) {
|
||||
constructor.getParameterList().add(parm);
|
||||
}
|
||||
if (parms.length > 0){
|
||||
body.append("super(");
|
||||
for(int j = 0; j < parms.length; j++) {
|
||||
PsiParameter parm = parms[j];
|
||||
if (j > 0){
|
||||
body.append(",");
|
||||
}
|
||||
body.append(parm.getName());
|
||||
}
|
||||
body.append(");\n");
|
||||
PsiParameter newParam = factory.createParameter(parm.getName(), parm.getType());
|
||||
copyModifierList(factory, parm, newParam);
|
||||
constructor.getParameterList().add(newParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JavaCodeStyleManager javaStyle = JavaCodeStyleManager.getInstance(aClass.getProject());
|
||||
|
||||
List<PsiParameter> fieldParams = new ArrayList<PsiParameter>();
|
||||
for (PsiField field : fields) {
|
||||
String fieldName = field.getName();
|
||||
String name = javaStyle.variableNameToPropertyName(fieldName, VariableKind.FIELD);
|
||||
@@ -280,22 +271,39 @@ public class GenerateConstructorHandler extends GenerateMembersHandlerBase {
|
||||
}
|
||||
|
||||
constructor.getParameterList().add(parm);
|
||||
if (fieldName.equals(parmName)) {
|
||||
body.append("this.");
|
||||
fieldParams.add(parm);
|
||||
}
|
||||
|
||||
ConstructorBodyGenerator generator = ConstructorBodyGenerator.INSTANCE.forLanguage(aClass.getLanguage());
|
||||
if (generator != null) {
|
||||
@NonNls StringBuilder buffer = new StringBuilder();
|
||||
generator.start(buffer, constructor.getName(), PsiParameter.EMPTY_ARRAY);
|
||||
if (isNotEnum) {
|
||||
generator.generateSuperCallIfNeeded(buffer, baseConstructor.getParameterList().getParameters());
|
||||
}
|
||||
body.append(fieldName);
|
||||
body.append("=");
|
||||
body.append(parmName);
|
||||
body.append(";\n");
|
||||
generator.generateFieldInitialization(buffer, fields, fieldParams.toArray(new PsiParameter[fieldParams.size()]));
|
||||
generator.finish(buffer);
|
||||
PsiMethod stub = factory.createMethodFromText(buffer.toString(), aClass);
|
||||
constructor.getBody().replace(stub.getBody());
|
||||
}
|
||||
|
||||
body.append("}");
|
||||
PsiCodeBlock bodyBlock = factory.createCodeBlockFromText(body.toString(), null);
|
||||
constructor.getBody().replace(bodyBlock);
|
||||
constructor = (PsiMethod)codeStyleManager.reformat(constructor);
|
||||
return constructor;
|
||||
}
|
||||
|
||||
static void copyModifierList(JVMElementFactory factory, PsiParameter parm, PsiParameter newParam) {
|
||||
PsiModifierList modifierList = parm.getModifierList();
|
||||
PsiModifierList newMList = newParam.getModifierList();
|
||||
if (modifierList != null && newMList != null) {
|
||||
for (PsiAnnotation annotation : modifierList.getAnnotations()) {
|
||||
newMList.add(factory.createAnnotationFromText(annotation.getText(), newParam));
|
||||
}
|
||||
for (@PsiModifier.ModifierConstant String m : PsiModifier.MODIFIERS) {
|
||||
newMList.setModifierProperty(m, parm.hasModifierProperty(m));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PsiModifier.ModifierConstant
|
||||
public static String getConstructorModifier(final PsiClass aClass) {
|
||||
String modifier = PsiModifier.PUBLIC;
|
||||
|
||||
@@ -172,7 +172,7 @@ public class GenerateMembersUtil {
|
||||
editor.getSelectionModel().removeSelection();
|
||||
}
|
||||
|
||||
public static PsiElement insert(PsiClass aClass, PsiMember member, PsiElement anchor, boolean before) throws IncorrectOperationException {
|
||||
public static PsiElement insert(@NotNull PsiClass aClass, @NotNull PsiMember member, @Nullable PsiElement anchor, boolean before) throws IncorrectOperationException {
|
||||
if (member instanceof PsiMethod) {
|
||||
if (!aClass.isInterface()) {
|
||||
final PsiParameter[] parameters = ((PsiMethod)member).getParameterList().getParameters();
|
||||
@@ -228,9 +228,15 @@ public class GenerateMembersUtil {
|
||||
|
||||
public static PsiMethod substituteGenericMethod(PsiMethod method,
|
||||
final PsiSubstitutor substitutor,
|
||||
final PsiElement target) {
|
||||
@Nullable final PsiElement target) {
|
||||
Project project = method.getProject();
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
|
||||
final JVMElementFactory factory;
|
||||
if (target != null) {
|
||||
factory = JVMElementFactories.getFactory(target.getLanguage(), method.getProject());
|
||||
}
|
||||
else {
|
||||
factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
|
||||
}
|
||||
|
||||
try {
|
||||
PsiType returnType = method.getReturnType();
|
||||
@@ -238,7 +244,7 @@ public class GenerateMembersUtil {
|
||||
PsiMethod newMethod;
|
||||
if (method.isConstructor()) {
|
||||
newMethod = factory.createConstructor();
|
||||
newMethod.getNameIdentifier().replace(factory.createIdentifier(method.getName()));
|
||||
newMethod.setName(method.getName());
|
||||
}
|
||||
else {
|
||||
final PsiType substitutedReturnType = substituteType(substitutor, returnType);
|
||||
@@ -292,10 +298,15 @@ public class GenerateMembersUtil {
|
||||
if (paramName == null) paramName = "p" + i;
|
||||
|
||||
PsiParameter newParameter = factory.createParameter(paramName, substituted);
|
||||
if (parameter.getLanguage() == JavaLanguage.INSTANCE) {
|
||||
if (parameter.getLanguage() == newParameter.getLanguage()) {
|
||||
PsiModifierList modifierList = newParameter.getModifierList();
|
||||
modifierList = (PsiModifierList)modifierList.replace(parameter.getModifierList());
|
||||
processAnnotations(project, modifierList, moduleScope);
|
||||
if (parameter.getLanguage() == JavaLanguage.INSTANCE) {
|
||||
processAnnotations(project, modifierList, moduleScope);
|
||||
}
|
||||
}
|
||||
else {
|
||||
GenerateConstructorHandler.copyModifierList(factory, parameter, newParameter);
|
||||
}
|
||||
newMethod.getParameterList().add(newParameter);
|
||||
}
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.codeInsight.generation;
|
||||
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class JavaConstructorBodyWithSuperCallGenerator implements ConstructorBodyGenerator {
|
||||
@Override
|
||||
public void generateFieldInitialization(@NotNull StringBuilder buffer,
|
||||
@NotNull PsiField[] fields,
|
||||
@NotNull PsiParameter[] parameters) {
|
||||
for (int i = 0, length = fields.length; i < length; i++) {
|
||||
String fieldName = fields[i].getName();
|
||||
String paramName = parameters[i].getName();
|
||||
if (fieldName.equals(paramName)) {
|
||||
buffer.append("this.");
|
||||
}
|
||||
buffer.append(fieldName);
|
||||
buffer.append("=");
|
||||
buffer.append(paramName);
|
||||
buffer.append(";\n");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateSuperCallIfNeeded(@NotNull StringBuilder buffer, @NotNull PsiParameter[] parameters) {
|
||||
if (parameters.length > 0) {
|
||||
buffer.append("super(");
|
||||
for (int j = 0; j < parameters.length; j++) {
|
||||
PsiParameter param = parameters[j];
|
||||
buffer.append(param.getName());
|
||||
if (j < parameters.length - 1) buffer.append(",");
|
||||
}
|
||||
buffer.append(");\n");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder start(StringBuilder buffer, @NotNull String name, @NotNull PsiParameter[] parameters) {
|
||||
buffer.append("public ").append(name).append("(");
|
||||
for (PsiParameter parameter : parameters) {
|
||||
buffer.append(parameter.getType().getPresentableText()).append(' ').append(parameter.getName()).append(',');
|
||||
}
|
||||
if (parameters.length > 0) {
|
||||
buffer.delete(buffer.length() - 1, buffer.length());
|
||||
}
|
||||
buffer.append("){\n");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(StringBuilder buffer) {
|
||||
buffer.append('}');
|
||||
}
|
||||
}
|
||||
@@ -127,4 +127,6 @@ public interface JVMElementFactory {
|
||||
|
||||
@NotNull
|
||||
PsiElement createExpressionFromText(@NotNull @NonNls String text, @Nullable PsiElement context) throws IncorrectOperationException;
|
||||
|
||||
PsiElement createReferenceElementByType(PsiClassType type);
|
||||
}
|
||||
|
||||
@@ -430,6 +430,9 @@
|
||||
<extensionPoint name="testCreator"
|
||||
beanClass="com.intellij.lang.LanguageExtensionPoint"/>
|
||||
|
||||
<extensionPoint name="constructorBodyGenerator"
|
||||
beanClass="com.intellij.lang.LanguageExtensionPoint"/>
|
||||
|
||||
<extensionPoint name="testGenerator"
|
||||
beanClass="com.intellij.lang.LanguageExtensionPoint"/>
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@
|
||||
<testFramework implementation="org.jetbrains.plugins.groovy.testIntegration.GroovyTestFramework"/>
|
||||
<testCreator language="Groovy" implementationClass="com.intellij.testIntegration.JavaTestCreator"/>
|
||||
<testGenerator language="Groovy" implementationClass="org.jetbrains.plugins.groovy.testIntegration.GroovyTestGenerator"/>
|
||||
<constructorBodyGenerator language="Groovy" implementationClass="org.jetbrains.plugins.groovy.annotator.intentions.dynamic.GrConstructorBodyGenerator"/>
|
||||
<editorNotificationProvider implementation="org.jetbrains.plugins.groovy.annotator.ConfigureGroovyLibraryNotificationProvider"/>
|
||||
<refactoring.introduceParameterMethodUsagesProcessor implementation="org.jetbrains.plugins.groovy.refactoring.introduce.parameter.java2groovy.GroovyIntroduceParameterMethodUsagesProcessor"/>
|
||||
<refactoring.changeSignatureUsageProcessor implementation="org.jetbrains.plugins.groovy.refactoring.changeSignature.GrChangeSignatureUsageProcessor" id="groovyProcessor" order="before javaProcessor"/>
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.JavaErrorMessages;
|
||||
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.AddMethodBodyFix;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.CreateConstructorMatchingSuperFix;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
|
||||
import com.intellij.codeInsight.generation.OverrideImplementUtil;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
@@ -429,7 +430,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
|
||||
if (constructors.length == 0) {
|
||||
if (!hasImplicitDefConstructor && (defConstructor == null || !PsiUtil.isAccessible(typeDefinition, defConstructor))) {
|
||||
final TextRange range = getClassHeaderTextRange(typeDefinition);
|
||||
holder.createErrorAnnotation(range, GroovyBundle.message("there.is.no.default.constructor.available.in.class.0", qName));
|
||||
holder.createErrorAnnotation(range, GroovyBundle.message("there.is.no.default.constructor.available.in.class.0", qName)).registerFix(new CreateConstructorMatchingSuperFix(typeDefinition));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 org.jetbrains.plugins.groovy.annotator.intentions.dynamic;
|
||||
|
||||
import com.intellij.codeInsight.generation.ConstructorBodyGenerator;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class GrConstructorBodyGenerator implements ConstructorBodyGenerator {
|
||||
@Override
|
||||
public void generateFieldInitialization(@NotNull StringBuilder buffer,
|
||||
@NotNull PsiField[] fields,
|
||||
@NotNull PsiParameter[] parameters) {
|
||||
for (int i = 0, length = fields.length; i < length; i++) {
|
||||
String fieldName = fields[i].getName();
|
||||
String paramName = parameters[i].getName();
|
||||
if (fieldName.equals(paramName)) {
|
||||
buffer.append("this.");
|
||||
}
|
||||
buffer.append(fieldName);
|
||||
buffer.append("=");
|
||||
buffer.append(paramName);
|
||||
buffer.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateSuperCallIfNeeded(@NotNull StringBuilder buffer, @NotNull PsiParameter[] parameters) {
|
||||
if (parameters.length > 0) {
|
||||
buffer.append("super(");
|
||||
for (int j = 0; j < parameters.length; j++) {
|
||||
PsiParameter param = parameters[j];
|
||||
buffer.append(param.getName());
|
||||
if (j < parameters.length - 1) buffer.append(",");
|
||||
}
|
||||
buffer.append(")\n");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder start(StringBuilder buffer, @NotNull String name, @NotNull PsiParameter[] parameters) {
|
||||
buffer.append("public ").append(name).append("(");
|
||||
for (PsiParameter parameter : parameters) {
|
||||
buffer.append(parameter.getType().getPresentableText()).append(' ').append(parameter.getName()).append(',');
|
||||
}
|
||||
if (parameters.length > 0) {
|
||||
buffer.delete(buffer.length() - 1, buffer.length());
|
||||
}
|
||||
buffer.append("){\n");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(StringBuilder buffer) {
|
||||
buffer.append('}');
|
||||
}
|
||||
}
|
||||
+4
@@ -151,4 +151,8 @@ public class GrClassReferenceType extends PsiClassType {
|
||||
public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) {
|
||||
return new GrClassReferenceType(myReferenceElement,languageLevel);
|
||||
}
|
||||
|
||||
public GrReferenceElement getReference() {
|
||||
return myReferenceElement;
|
||||
}
|
||||
}
|
||||
|
||||
+27
-5
@@ -154,6 +154,21 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
|
||||
return (GrExpression) topStatements[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrCodeReferenceElement createReferenceElementByType(PsiClassType type) {
|
||||
if (type instanceof GrClassReferenceType) {
|
||||
GrReferenceElement reference = ((GrClassReferenceType)type).getReference();
|
||||
if (reference instanceof GrCodeReferenceElement) {
|
||||
return (GrCodeReferenceElement)reference;
|
||||
}
|
||||
}
|
||||
|
||||
final PsiClassType.ClassResolveResult resolveResult = type.resolveGenerics();
|
||||
final PsiClass refClass = resolveResult.getElement();
|
||||
assert refClass != null : type;
|
||||
return createCodeReferenceElementFromText(type.getPresentableText());
|
||||
}
|
||||
|
||||
public GrVariableDeclaration createVariableDeclaration(@Nullable String[] modifiers,
|
||||
@Nullable GrExpression initializer,
|
||||
@Nullable PsiType type,
|
||||
@@ -397,12 +412,19 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
|
||||
return createConstructorFromText(constructorName, text, context);
|
||||
}
|
||||
|
||||
public GrMethod createConstructorFromText(String constructorName, String text, @Nullable PsiElement context) {
|
||||
GroovyFileImpl file = createDummyFile("class " + constructorName + "{" + text + "}");
|
||||
public GrMethod createConstructorFromText(String constructorName, String constructorText, @Nullable PsiElement context) {
|
||||
GroovyFileImpl file = createDummyFile("class " + constructorName + "{" + constructorText + "}");
|
||||
file.setContext(context);
|
||||
GrTopLevelDefinition definition = file.getTopLevelDefinitions()[0];
|
||||
assert definition != null && definition instanceof GrClassDefinition;
|
||||
return ((GrClassDefinition) definition).getGroovyMethods()[0];
|
||||
|
||||
if (!( definition != null && definition instanceof GrClassDefinition)) {
|
||||
throw new IncorrectOperationException("constructorName: " + constructorName + ", text: " + constructorText);
|
||||
}
|
||||
GrMethod[] methods = ((GrClassDefinition)definition).getGroovyMethods();
|
||||
if (methods.length != 1) {
|
||||
throw new IncorrectOperationException("constructorName: " + constructorName + ", text: " + constructorText);
|
||||
}
|
||||
return methods[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -842,7 +864,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiMethod createConstructor() {
|
||||
return createConstructorFromText("Foo", "", null);
|
||||
return createConstructorFromText("Foo", "Foo(){}", null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -524,7 +524,6 @@ public class PsiImplUtil {
|
||||
return AstBufferUtil.getTextSkippingWhitespaceComments(node);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiCodeBlock getOrCreatePsiCodeBlock(GrOpenBlock block) {
|
||||
if (block == null) return null;
|
||||
|
||||
|
||||
+16
@@ -15,20 +15,25 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.synthetic;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
|
||||
|
||||
/**
|
||||
* @author Medvedev Max
|
||||
*/
|
||||
public class GrSyntheticCodeBlock extends LightElement implements PsiCodeBlock {
|
||||
private static final Logger LOG = Logger.getInstance(GrSyntheticCodeBlock.class);
|
||||
private GrCodeBlock myCodeBlock;
|
||||
private static final Key<SoftReference<PsiJavaToken>> PSI_JAVA_TOKEN = Key.create("psi_java_token");
|
||||
|
||||
@@ -86,6 +91,17 @@ public class GrSyntheticCodeBlock extends LightElement implements PsiCodeBlock {
|
||||
return newToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement replace(@NotNull PsiElement newElement) throws IncorrectOperationException {
|
||||
if (newElement instanceof GrSyntheticCodeBlock) {
|
||||
GrSyntheticCodeBlock other = (GrSyntheticCodeBlock)newElement;
|
||||
PsiElement replaced = myCodeBlock.replace(other.myCodeBlock);
|
||||
LOG.assertTrue(replaced instanceof GrOpenBlock);
|
||||
return PsiImplUtil.getOrCreatePsiCodeBlock((GrOpenBlock)replaced);
|
||||
}
|
||||
return super.replace(newElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldChangeModificationCount(PsiElement place) {
|
||||
return false;
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 org.jetbrains.plugins.groovy.intentions
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class AddConstructorMatchingSuperTest extends GrIntentionTestCase {
|
||||
private static final String HINT = "Create constructor matching super"
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "${TestUtils.testDataPath}intentions/constructorMatchingSuper/"
|
||||
}
|
||||
|
||||
void testGroovyToGroovy() {
|
||||
doTextTest('''\
|
||||
class Base {
|
||||
Base(int p, @Anno int x) throws Exception {}
|
||||
}
|
||||
|
||||
class Derived exten<caret>ds Base {
|
||||
}
|
||||
''', HINT, '''\
|
||||
class Base {
|
||||
Base(int p, @Anno int x) throws Exception {}
|
||||
}
|
||||
|
||||
class Derived extends Base {
|
||||
<caret>Derived(int p, @Anno int x) throws Exception {
|
||||
super(p, x)
|
||||
}
|
||||
}
|
||||
''')
|
||||
}
|
||||
|
||||
void testJavaToGroovy() {
|
||||
myFixture.addClass('''\
|
||||
class Base {
|
||||
Base(int p, @Anno int x) throws Exception {}
|
||||
}
|
||||
''')
|
||||
doTextTest('''\
|
||||
class Derived exten<caret>ds Base {
|
||||
}
|
||||
''', HINT, '''\
|
||||
class Derived extends Base {
|
||||
<caret>def Derived(int p, @Anno int x) throws Exception {
|
||||
super(p, x)
|
||||
}
|
||||
}
|
||||
''')
|
||||
}
|
||||
|
||||
void testGroovyToJava() {
|
||||
myFixture.addClass('''\
|
||||
class Base {
|
||||
Base(int p, @Override int x) throws Exception {}
|
||||
}
|
||||
''')
|
||||
myFixture.configureByText("a.java", '''\
|
||||
class Derived exten<caret>ds Base {
|
||||
}
|
||||
''')
|
||||
final List<IntentionAction> list = myFixture.filterAvailableIntentions(HINT)
|
||||
myFixture.launchAction(assertOneElement(list))
|
||||
PostprocessReformattingAspect.getInstance(project).doPostponedFormatting()
|
||||
myFixture.checkResult('''\
|
||||
class Derived extends Base {
|
||||
<caret>Derived(int p, @Override int x) throws Exception {
|
||||
super(p, x);
|
||||
}
|
||||
}
|
||||
''')
|
||||
}
|
||||
|
||||
}
|
||||
+6
-7
@@ -16,11 +16,10 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.intentions;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
|
||||
import java.util.List;
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
@@ -31,14 +30,14 @@ public abstract class GrIntentionTestCase extends LightCodeInsightFixtureTestCas
|
||||
final List<IntentionAction> list = myFixture.filterAvailableIntentions(hint);
|
||||
if (intentionExists) {
|
||||
myFixture.launchAction(assertOneElement(list));
|
||||
PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
|
||||
PostprocessReformattingAspect.getInstance(project).doPostponedFormatting();
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.groovy");
|
||||
}
|
||||
else {
|
||||
if (list.size() > 0) {
|
||||
StringBuilder text = new StringBuilder("available intentions:");
|
||||
for (IntentionAction intentionAction : list) {
|
||||
text.append(intentionAction.getFamilyName()).append(", ");
|
||||
text.append(intentionAction.familyName).append(", ");
|
||||
}
|
||||
fail(text.toString());
|
||||
}
|
||||
@@ -49,7 +48,7 @@ public abstract class GrIntentionTestCase extends LightCodeInsightFixtureTestCas
|
||||
myFixture.configureByText("a.groovy", before);
|
||||
final List<IntentionAction> list = myFixture.filterAvailableIntentions(hint);
|
||||
myFixture.launchAction(assertOneElement(list));
|
||||
PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
|
||||
PostprocessReformattingAspect.getInstance(project).doPostponedFormatting();
|
||||
myFixture.checkResult(after);
|
||||
}
|
||||
|
||||
@@ -820,6 +820,8 @@
|
||||
|
||||
<debuggerEditorTextProvider language="JAVA" implementationClass="com.intellij.debugger.impl.JavaEditorTextProviderImpl"/>
|
||||
|
||||
<constructorBodyGenerator language="JAVA" implementationClass="com.intellij.codeInsight.generation.JavaConstructorBodyWithSuperCallGenerator"/>
|
||||
|
||||
<quoteHandler fileType="JAVA" className="com.intellij.codeInsight.editorActions.JavaQuoteHandler"/>
|
||||
<typedHandler implementation="com.intellij.codeInsight.editorActions.JavaTypedHandler" id="java"/>
|
||||
<typedHandler implementation="com.intellij.codeInsight.editorActions.JavadocTypedHandler" id="javadoc"/>
|
||||
|
||||
Reference in New Issue
Block a user