IDEA-79715 Groovy: Inspection "There is no default constructor available in class *" must have a quickfix

This commit is contained in:
Maxim.Medvedev
2012-04-25 18:00:55 +04:00
parent e856e8f135
commit ed0afd2ce7
17 changed files with 408 additions and 66 deletions
@@ -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);
}
@@ -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);
}
@@ -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"/>
+1
View File
@@ -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;
}
@@ -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('}');
}
}
@@ -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;
}
}
@@ -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;
@@ -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;
@@ -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);
}
}
''')
}
}
@@ -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);
}
+2
View File
@@ -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"/>