OverrideImplementUtil instead of GroovyOverrideImplementUtil

This commit is contained in:
Maxim Medvedev
2011-06-17 13:05:26 +04:00
parent 9383f77e49
commit f2c6b8e1d7
23 changed files with 316 additions and 184 deletions
@@ -40,8 +40,10 @@ public class GroovyGenerationInfo<T extends PsiMember> extends PsiGenerationInfo
public void insert(PsiClass aClass, PsiElement anchor, boolean before) throws IncorrectOperationException {
super.insert(aClass, anchor, before);
final T member = getPsiMember();
assert member instanceof GroovyPsiElement;
PsiUtil.shortenReferences((GroovyPsiElement)member);
if (member != null) {
assert member instanceof GroovyPsiElement;
PsiUtil.shortenReferences((GroovyPsiElement)member);
}
}
@Override
@@ -17,6 +17,7 @@
package org.jetbrains.plugins.groovy.annotator;
import com.intellij.codeInsight.daemon.impl.quickfix.AddMethodBodyFix;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.ASTNode;
@@ -98,7 +99,6 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.noncode.GrInheritConstructorContributor;
import org.jetbrains.plugins.groovy.lang.resolve.processors.PropertyResolverProcessor;
import org.jetbrains.plugins.groovy.overrideImplement.GroovyOverrideImplementUtil;
import org.jetbrains.plugins.groovy.overrideImplement.quickFix.ImplementMethodsQuickFix;
import java.util.ArrayList;
@@ -919,7 +919,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
if (typeDefinition.isAnnotationType()) return;
if (typeDefinition instanceof GrTypeParameter) return;
Collection<CandidateInfo> collection = GroovyOverrideImplementUtil.getMethodsToImplement(typeDefinition);
Collection<CandidateInfo> collection = OverrideImplementUtil.getMethodsToOverrideImplement(typeDefinition, true);
if (collection.isEmpty()) return;
final PsiElement element = collection.iterator().next().getElement();
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.groovy.intentions.style;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
@@ -36,7 +37,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousC
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.overrideImplement.GroovyOverrideImplementUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil;
import java.util.*;
@@ -86,7 +86,7 @@ public class ReplaceAbstractClassInstanceByMapIntention extends Intention {
}
final PsiClass iface = (PsiClass)resolved;
final Collection<CandidateInfo> collection = GroovyOverrideImplementUtil.getMethodsToImplement(anonymous);
final Collection<CandidateInfo> collection = OverrideImplementUtil.getMethodsToOverrideImplement(anonymous, true);
for (CandidateInfo info : collection) {
myMethodToBodyMap.put((PsiMethod)info.getElement(), Collections.<PsiElement>emptyList());
}
@@ -44,6 +44,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrExtendsClause;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrImplementsClause;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrConstructor;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.GrTopStatement;
@@ -178,16 +179,18 @@ public abstract class GroovyPsiElementFactory {
public abstract GrMethod createMethodFromText(String modifier, String name, String type, String[] paramTypes, PsiElement context);
public abstract GrMethod createConstructorFromText(@NotNull String constructorName,
public abstract GrConstructor createConstructorFromText(@NotNull String constructorName,
String[] paramTypes,
String[] paramNames,
String body,
@Nullable PsiElement context);
public GrMethod createConstructorFromText(@NotNull String constructorName, String[] paramTypes, String[] paramNames, String body) {
public GrConstructor createConstructorFromText(@NotNull String constructorName, String[] paramTypes, String[] paramNames, String body) {
return createConstructorFromText(constructorName, paramTypes, paramNames, body, null);
}
public abstract GrConstructor createConstructorFromText(String constructorName, String text, @Nullable PsiElement context);
public abstract GrLabel createLabel(@NotNull String name);
public abstract GrDocComment createDocCommentFromText(String text) ;
@@ -16,16 +16,16 @@
package org.jetbrains.plugins.groovy.lang.psi.api.statements;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrCondition;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.GrTopStatement;
import com.intellij.util.IncorrectOperationException;
/**
* @author: Dmitry.Krasilschikov
* @date: 21.03.2007
*/
public interface GrStatement extends GrTopStatement, GrCondition {
public static final GrStatement[] EMPTY_ARRAY = new GrStatement[0];
GrStatement[] EMPTY_ARRAY = new GrStatement[0];
<T extends GrStatement> T replaceWithStatement (T statement);
@@ -20,19 +20,17 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrDeclarationHolder;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrDeclarationHolder;
/**
* @author ilyas
*/
public interface GrCodeBlock extends GrControlFlowOwner, GrVariableDeclarationOwner, GrStatementOwner, GrDeclarationHolder {
@Nullable
@NotNull
PsiElement getLBrace();
@Nullable
PsiElement getRBrace();
}
@@ -16,8 +16,6 @@
package org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrCondition;
/**
* @author ilyas
*/
@@ -57,7 +57,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatem
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.types.*;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrConstructorImpl;
import java.util.ArrayList;
import java.util.List;
@@ -380,20 +379,23 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
return createReferenceExpressionFromText("a" + newDot + "b").getDotToken();
}
public GrConstructorImpl createConstructorFromText(@NotNull String constructorName,
public GrConstructor createConstructorFromText(@NotNull String constructorName,
@Nullable String[] paramTypes,
String[] paramNames,
String body,
PsiElement context) {
final String text = generateMethodText(null, constructorName, null, paramTypes, paramNames, body, true);
return createConstructorFromText(constructorName, text, context);
}
public GrConstructor createConstructorFromText(String constructorName, String text, @Nullable PsiElement context) {
GroovyFileImpl file = createDummyFile("class " + constructorName + "{" + text + "}");
file.setContext(context);
GrTopLevelDefinition definition = file.getTopLevelDefinitions()[0];
assert definition != null && definition instanceof GrClassDefinition;
final PsiMethod constructor = ((GrClassDefinition) definition).getMethods()[0];
assert constructor instanceof GrConstructorImpl;
return ((GrConstructorImpl) constructor);
assert constructor instanceof GrConstructor;
return ((GrConstructor) constructor);
}
@Override
@@ -180,7 +180,7 @@ public abstract class GrBlockImpl extends LazyParseablePsiElement implements GrC
return text.contains("\n") || text.contains("\r");
}
@Nullable
@NotNull
public PsiElement getLBrace() {
return findPsiChildByType(GroovyTokenTypes.mLCURLY);
}
@@ -18,6 +18,7 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members;
import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import com.intellij.psi.impl.ElementPresentationUtil;
import com.intellij.psi.impl.PsiClassImplUtil;
@@ -28,6 +29,7 @@ import com.intellij.psi.search.SearchScope;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.reference.SoftReference;
import com.intellij.ui.RowIcon;
import com.intellij.util.*;
import org.jetbrains.annotations.NonNls;
@@ -60,6 +62,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GrStubElementBase;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrSyntheticCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.stubs.GrMethodStub;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.MethodTypeInferencer;
@@ -73,6 +76,8 @@ import java.util.List;
*/
public abstract class GrMethodBaseImpl extends GrStubElementBase<GrMethodStub> implements GrMethod, StubBasedPsiElement<GrMethodStub> {
private static final Key<SoftReference<PsiCodeBlock>> PSI_CODE_BLOCK = Key.create("Psi_code_block");
protected GrMethodBaseImpl(final GrMethodStub stub, IStubElementType nodeType) {
super(stub, nodeType);
}
@@ -295,7 +300,15 @@ public abstract class GrMethodBaseImpl extends GrStubElementBase<GrMethodStub> i
@Nullable
public PsiCodeBlock getBody() {
return null;
final GrOpenBlock block = getBlock();
if (block == null) return null;
final SoftReference<PsiCodeBlock> ref = block.getUserData(PSI_CODE_BLOCK);
final PsiCodeBlock body = ref == null ? null : ref.get();
if (body != null) return body;
final GrSyntheticCodeBlock newBody = new GrSyntheticCodeBlock(block);
block.putUserData(PSI_CODE_BLOCK, new SoftReference<PsiCodeBlock>(newBody));
return newBody;
}
public boolean isConstructor() {
@@ -499,4 +512,4 @@ public abstract class GrMethodBaseImpl extends GrStubElementBase<GrMethodStub> i
public boolean isEquivalentTo(PsiElement another) {
return PsiClassImplUtil.isMethodEquivalentTo(this, another);
}
}
}
@@ -0,0 +1,129 @@
/*
* Copyright 2000-2011 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.lang.psi.impl.synthetic;
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 org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
/**
* @author Medvedev Max
*/
public class GrSyntheticCodeBlock extends LightElement implements PsiCodeBlock {
private GrCodeBlock myCodeBlock;
private static final Key<SoftReference<PsiJavaToken>> PSI_JAVA_TOKEN = Key.create("psi_java_token");
public GrSyntheticCodeBlock(@NotNull GrCodeBlock codeBlock) {
super(codeBlock.getManager(), codeBlock.getLanguage());
myCodeBlock = codeBlock;
}
@Override
public String toString() {
return "code block wrapper to represent java codeBlock";
}
@NotNull
@Override
public PsiStatement[] getStatements() {
return PsiStatement.EMPTY_ARRAY; //todo return statements
}
@Override
public PsiElement getFirstBodyElement() {
final PsiElement nextSibling = myCodeBlock.getLBrace().getNextSibling();
return nextSibling == getRBrace() ? null : nextSibling;
}
@Override
public PsiElement getLastBodyElement() {
final PsiElement rBrace = myCodeBlock.getRBrace();
if (rBrace != null) {
final PsiElement prevSibling = rBrace.getPrevSibling();
return prevSibling == myCodeBlock.getLBrace() ? null : prevSibling;
}
return getLastChild();
}
@Override
public PsiJavaToken getLBrace() {
return getOrCreateJavaToken(myCodeBlock.getLBrace(), JavaTokenType.LBRACE);
}
@Override
public PsiJavaToken getRBrace() {
return getOrCreateJavaToken(myCodeBlock.getRBrace(), JavaTokenType.RBRACE);
}
@Nullable
private static PsiJavaToken getOrCreateJavaToken(@Nullable PsiElement element, @NotNull IElementType type) {
if (element == null) return null;
final SoftReference<PsiJavaToken> ref = element.getUserData(PSI_JAVA_TOKEN);
final PsiJavaToken token = ref == null ? null : ref.get();
if (token != null) return token;
final LightJavaToken newToken = new LightJavaToken(element, type);
element.putUserData(PSI_JAVA_TOKEN, new SoftReference<PsiJavaToken>(newToken));
return newToken;
}
@Override
public boolean shouldChangeModificationCount(PsiElement place) {
return false;
}
@Override
public TextRange getTextRange() {
return myCodeBlock.getTextRange();
}
@Override
public int getStartOffsetInParent() {
return myCodeBlock.getStartOffsetInParent();
}
@Override
public PsiFile getContainingFile() {
return myCodeBlock.getContainingFile();
}
@Override
public int getTextOffset() {
return myCodeBlock.getTextOffset();
}
@Override
public String getText() {
return myCodeBlock.getText();
}
@NotNull
@Override
public PsiElement getNavigationElement() {
return myCodeBlock;
}
@Override
public boolean isValid() {
return myCodeBlock.isValid();
}
}
@@ -70,5 +70,8 @@ public class JavaIdentifier extends LightIdentifier {
return myElement.getNextSibling();
}
@Override
public PsiElement copy() {
return new JavaIdentifier(myManager, myElement);
}
}
@@ -0,0 +1,90 @@
/*
* Copyright 2000-2011 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.lang.psi.impl.synthetic;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaToken;
import com.intellij.psi.impl.light.LightElement;
import com.intellij.psi.tree.IElementType;
/**
* @author Medvedev Max
*/
public class LightJavaToken extends LightElement implements PsiJavaToken {
private PsiElement myElement;
private IElementType myType;
public LightJavaToken(PsiElement element, IElementType type) {
super(element.getManager(), element.getLanguage());
myElement = element;
myType = type;
}
@Override
public boolean isValid() {
return myElement.isValid();
}
@Override
public String toString() {
return "light java token";
}
public TextRange getTextRange() {
return myElement.getTextRange();
}
public PsiFile getContainingFile() {
return myElement.getContainingFile();
}
@Override
public int getStartOffsetInParent() {
return myElement.getStartOffsetInParent();
}
@Override
public int getTextOffset() {
return myElement.getTextOffset();
}
@Override
public PsiElement getParent() {
return myElement.getParent();
}
@Override
public PsiElement getPrevSibling() {
return myElement.getPrevSibling();
}
@Override
public PsiElement getNextSibling() {
return myElement.getNextSibling();
}
@Override
public PsiElement copy() {
return new LightJavaToken(myElement, myType);
}
@Override
public IElementType getTokenType() {
return myType;
}
}
@@ -15,9 +15,11 @@
*/
package org.jetbrains.plugins.groovy.overrideImplement;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.lang.LanguageCodeInsightActionHandler;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.GroovyFileType;
@@ -32,7 +34,10 @@ public class GroovyImplementMethodsHandler implements LanguageCodeInsightActionH
}
public void invoke(@NotNull final Project project, @NotNull Editor editor, @NotNull PsiFile file) {
GroovyOverrideImplementUtil.invokeOverrideImplement(editor, file, true);
PsiClass aClass = OverrideImplementUtil.getContextClass(project, editor, file, true);
if (aClass != null) {
OverrideImplementUtil.chooseAndImplementMethods(project, editor, aClass);
}
}
public boolean startInWriteAction() {
@@ -15,40 +15,31 @@
*/
package org.jetbrains.plugins.groovy.overrideImplement;
import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.codeInsight.generation.PsiMethodMember;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.fileTemplates.JavaTemplateUtil;
import com.intellij.ide.util.MemberChooser;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
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;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTopLevelDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.refactoring.convertToJava.ModifierListGenerator;
import java.io.IOException;
import java.util.*;
@@ -67,52 +58,27 @@ public class GroovyOverrideImplementUtil {
public static void invokeOverrideImplement(final Editor editor, final PsiFile file, final boolean isImplement) {
final int offset = editor.getCaretModel().getOffset();
GrTypeDefinition aClass = PsiTreeUtil.findElementOfClassAtOffset(file, offset, GrTypeDefinition.class, false);
if (aClass == null) {
return;
}
final GrTypeDefinition aClass = PsiTreeUtil.findElementOfClassAtOffset(file, offset, GrTypeDefinition.class, false);
if (aClass == null) return;
if (isImplement && aClass.isInterface()) return;
Collection<CandidateInfo> candidates = getMethodsToOverrideImplement(aClass, isImplement);
Collection<CandidateInfo> secondary = isImplement ? Collections.<CandidateInfo>emptyList() : getMethodsToOverrideImplement(aClass, !isImplement);
Collection<CandidateInfo> candidates = OverrideImplementUtil.getMethodsToOverrideImplement(aClass, isImplement);
Collection<CandidateInfo> secondary = isImplement ? Collections.<CandidateInfo>emptyList() : OverrideImplementUtil.getMethodsToOverrideImplement(aClass, !isImplement);
MemberChooser<PsiMethodMember> chooser = OverrideImplementUtil.showOverrideImplementChooser(editor, aClass, isImplement, candidates, secondary);
final MemberChooser<PsiMethodMember> chooser = OverrideImplementUtil.showOverrideImplementChooser(editor, aClass, isImplement, candidates, secondary);
if (chooser == null) return;
final List<PsiMethodMember> selectedElements = chooser.getSelectedElements();
if (selectedElements == null || selectedElements.size() == 0) return;
for (PsiMethodMember methodMember : selectedElements) {
if (!aClass.isValid()) {
aClass = PsiTreeUtil.findElementOfClassAtOffset(file, offset, GrTypeDefinition.class, false);
assert aClass != null;
new WriteCommandAction(aClass.getProject(), aClass.getContainingFile()) {
protected void run(final Result result) throws Throwable {
OverrideImplementUtil.overrideOrImplementMethodsInRightPlace(editor, aClass, selectedElements, chooser.isCopyJavadoc(), chooser.isInsertOverrideAnnotation());
}
generateImplementation(editor, aClass, methodMember.getElement(), methodMember.getSubstitutor());
}
}
}.execute();
public static void generateImplementation(@Nullable final Editor editor,
final GrTypeDefinition aClass,
final PsiMethod method,
final PsiSubstitutor substitutor) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
final PsiElement anchor = findAnchor(aClass, editor);
final GrMethod result = generateMethodPrototype(aClass, method, substitutor);
final GrMethod addedMethod = aClass.addMemberDeclaration(result, anchor);
PsiUtil.shortenReferences(addedMethod);
PsiFile psiFile = aClass.getContainingFile();
FileEditorManager fileEditorManager = FileEditorManager.getInstance(aClass.getProject());
Editor editor = fileEditorManager.openTextEditor(new OpenFileDescriptor(psiFile.getProject(), psiFile.getVirtualFile()), false);
if (editor == null) return;
GenerateMembersUtil.positionCaret(editor, addedMethod, true);
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
}
});
}
public static GrMethod generateMethodPrototype(GrTypeDefinition aClass,
@@ -135,82 +101,8 @@ public class GroovyOverrideImplementUtil {
return result;
}
@Nullable
private static PsiElement findAnchor(GrTypeDefinition aClass, Editor editor) {
PsiFile file = aClass.getContainingFile();
final GrTypeDefinitionBody classBody = aClass.getBody();
final PsiMethod[] methods = aClass.getMethods();
PsiElement anchor = null;
final PsiElement atCaret;
final GrTopLevelDefinition previousTopLevelElement;
if (editor == null) {
atCaret = null;
previousTopLevelElement = null;
}
else {
final int caretPosition = editor.getCaretModel().getOffset();
atCaret = file.findElementAt(caretPosition);
previousTopLevelElement = PsiUtil.findPreviousTopLevelElementByThisElement(atCaret);
}
if (atCaret != null && atCaret.getParent() instanceof GrTypeDefinitionBody) {
if (GroovyTokenTypes.mRCURLY.equals(atCaret.getNode().getElementType())) {
anchor = atCaret.getPrevSibling();
} else {
anchor = atCaret;
}
if (GroovyTokenTypes.mLCURLY.equals(anchor.getNode().getElementType())) {
anchor = anchor.getNextSibling();
}
} else if (previousTopLevelElement != null && previousTopLevelElement instanceof GrMethod) {
final PsiElement nextElement = previousTopLevelElement.getNextSibling();
if (nextElement != null) {
anchor = nextElement;
}
} else if (methods.length != 0) {
final PsiMethod lastMethod = methods[methods.length - 1];
if (lastMethod != null) {
final PsiElement nextSibling = lastMethod.getNextSibling();
if (nextSibling != null) {
anchor = nextSibling;
}
}
} else {
final PsiElement firstChild = classBody.getFirstChild();
assert firstChild != null;
final PsiElement nextElement = firstChild.getNextSibling();
assert nextElement != null;
anchor = nextElement;
}
return anchor;
}
public static Collection<CandidateInfo> getMethodsToOverrideImplement(GrTypeDefinition aClass, boolean isImplement) {
return OverrideImplementUtil.getMethodsToOverrideImplement(aClass, isImplement);
}
private static boolean writeMethodModifiers(StringBuffer text, PsiModifierList modifierList, String[] modifiers) {
boolean wasAddedModifiers = false;
for (@Modifier String modifierType : modifiers) {
if (modifierList.hasModifierProperty(modifierType) && modifierType != PsiModifier.PUBLIC) {
text.append(modifierType);
text.append(" ");
wasAddedModifiers = true;
}
}
return wasAddedModifiers;
}
private static final String[] GROOVY_MODIFIERS = new String[]{
PsiModifier.PUBLIC,
//PsiModifier.PUBLIC,
PsiModifier.PROTECTED,
PsiModifier.PRIVATE,
PsiModifier.STATIC,
@@ -221,8 +113,8 @@ public class GroovyOverrideImplementUtil {
private static GrMethod createOverrideImplementMethodSignature(Project project, PsiMethod superMethod, PsiSubstitutor substitutor, PsiClass aClass) {
StringBuffer buffer = new StringBuffer();
final boolean hasModifiers = writeMethodModifiers(buffer, superMethod.getModifierList(), GROOVY_MODIFIERS);
StringBuilder buffer = new StringBuilder();
final boolean hasModifiers = ModifierListGenerator.writeModifiers(buffer, superMethod.getModifierList(), GROOVY_MODIFIERS, false);
final PsiTypeParameter[] superTypeParameters = superMethod.getTypeParameters();
final List<PsiTypeParameter> typeParameters = new ArrayList<PsiTypeParameter>();
@@ -247,16 +139,19 @@ public class GroovyOverrideImplementUtil {
buffer.replace(buffer.length() - 2, buffer.length(), ">");
}
final String name;
if (superMethod.isConstructor()) {
buffer.append(aClass.getName());
name = aClass.getName();
}
else {
if (returnType != null) {
buffer.append(returnType.getCanonicalText()).append(" ");
}
buffer.append(superMethod.getName());
name = superMethod.getName();
}
buffer.append(name);
buffer.append("(");
final PsiParameter[] parameters = superMethod.getParameterList().getParameters();
for (int i = 0; i < parameters.length; i++) {
@@ -276,7 +171,11 @@ public class GroovyOverrideImplementUtil {
buffer.append(") {}");
return (GrMethod) GroovyPsiElementFactory.getInstance(project).createTopElementFromText(buffer.toString());
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project);
if (superMethod.isConstructor()) {
return factory.createConstructorFromText(name, buffer.toString(), null);
}
return (GrMethod) factory.createTopElementFromText(buffer.toString());
}
@Nullable
@@ -339,16 +238,4 @@ public class GroovyOverrideImplementUtil {
buffer.append(")");
return buffer.toString();
}
public static Collection<CandidateInfo> getMethodsToImplement(PsiClass typeDefinition) {
Collection<CandidateInfo> methodsToImplement = OverrideImplementUtil.getMethodsToOverrideImplement(typeDefinition, true);
methodsToImplement = ContainerUtil.findAll(methodsToImplement, new Condition<CandidateInfo>() {
public boolean value(CandidateInfo candidateInfo) {
//noinspection ConstantConditions
return !GroovyCommonClassNames.DEFAULT_BASE_CLASS_NAME
.equals(((PsiMethod)candidateInfo.getElement()).getContainingClass().getQualifiedName());
}
});
return methodsToImplement;
}
}
@@ -15,9 +15,11 @@
*/
package org.jetbrains.plugins.groovy.overrideImplement;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.lang.LanguageCodeInsightActionHandler;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.GroovyFileType;
@@ -32,7 +34,10 @@ public class GroovyOverrideMethodsHandler implements LanguageCodeInsightActionHa
}
public void invoke(@NotNull final Project project, @NotNull Editor editor, @NotNull PsiFile file) {
GroovyOverrideImplementUtil.invokeOverrideImplement(editor, file, false);
PsiClass aClass = OverrideImplementUtil.getContextClass(project, editor, file, true);
if (aClass != null) {
OverrideImplementUtil.chooseAndOverrideMethods(project, editor, aClass);
}
}
public boolean startInWriteAction() {
@@ -1,5 +1,6 @@
package org.jetbrains.plugins.groovy.lang
import com.intellij.codeInsight.generation.OverrideImplementUtil
import com.intellij.codeInsight.lookup.LookupManager
import com.intellij.codeInsight.navigation.GotoImplementationHandler
import com.intellij.openapi.module.Module
@@ -16,11 +17,8 @@ import org.jetbrains.annotations.NotNull
import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod
import org.jetbrains.plugins.groovy.overrideImplement.GroovyOverrideImplementUtil
import org.jetbrains.plugins.groovy.util.TestUtils
import com.intellij.psi.*
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl
/**
* @author peter
@@ -302,13 +300,13 @@ class Bar implements Intf {
class BarImpl extends Bar {}
"""
def facade = JavaPsiFacade.getInstance(getProject())
assertOneElement(GroovyOverrideImplementUtil.getMethodsToOverrideImplement(facade.findClass("Foo"), true))
assertOneElement(OverrideImplementUtil.getMethodsToOverrideImplement(facade.findClass("Foo"), true))
GrTypeDefinition barClass = facade.findClass("Bar")
assertEmpty(GroovyOverrideImplementUtil.getMethodsToOverrideImplement(barClass, true))
assertTrue "bar" in GroovyOverrideImplementUtil.getMethodsToOverrideImplement(barClass, false).collect { ((PsiMethod) it.element).name }
assertEmpty(OverrideImplementUtil.getMethodsToOverrideImplement(barClass, true))
assertTrue "bar" in OverrideImplementUtil.getMethodsToOverrideImplement(barClass, false).collect { ((PsiMethod) it.element).name }
assertEmpty(GroovyOverrideImplementUtil.getMethodsToOverrideImplement(facade.findClass("BarImpl"), true))
assertEmpty(OverrideImplementUtil.getMethodsToOverrideImplement(facade.findClass("BarImpl"), true))
def implementations = new GotoImplementationHandler().getSourceAndTargetElements(myFixture.editor, myFixture.file).targets
assertEquals Arrays.toString(implementations), 3, implementations.size()
@@ -1,15 +1,14 @@
package org.jetbrains.plugins.groovy.lang.overriding;
import com.intellij.codeInsight.generation.OverrideImplementUtil
import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiClassOwner
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiSubstitutor
import com.intellij.psi.impl.source.PostprocessReformattingAspect
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition
import org.jetbrains.plugins.groovy.overrideImplement.GroovyOverrideImplementUtil
/**
* @author peter
@@ -105,11 +104,11 @@ class Test extends Base<String> {
}
private def generateImplementation(PsiMethod method) {
GrTypeDefinition clazz = ((PsiClassOwner) myFixture.file).classes[0]
GroovyOverrideImplementUtil.generateImplementation myFixture.editor, clazz, method, PsiSubstitutor.EMPTY
ApplicationManager.application.runWriteAction(new Runnable() {
@Override
void run() {
GrTypeDefinition clazz = ((PsiClassOwner) myFixture.file).classes[0]
OverrideImplementUtil.overrideOrImplement(clazz, method);
PostprocessReformattingAspect.getInstance(myFixture.project).doPostponedFormatting()
}
});
@@ -4,6 +4,6 @@ class ConstructorAtEnd {
}
<caret>ConstructorAtEnd() {
ConstructorAtEnd() {<caret>
}
}
@@ -4,7 +4,7 @@ class ConstructorAtOffset {
}
<caret>ConstructorAtOffset() {
ConstructorAtOffset() {<caret>
}
def bar() {
@@ -1,5 +1,5 @@
class LonelyConstructor {
<caret>LonelyConstructor() {
LonelyConstructor() {<caret>
}
}
@@ -1,4 +1,4 @@
class <error descr="Cyclic inheritance involving 'Foo'">Foo</error> extends Bar {}
class <error descr="Cyclic inheritance involving 'Bar'">Bar</error> extends Foo {}
class <error descr="Method 'invokeMethod' is not implemented"><error descr="Cyclic inheritance involving 'Foo'">Foo</error></error> extends Bar {}
class <error descr="Method 'invokeMethod' is not implemented"><error descr="Cyclic inheritance involving 'Bar'">Bar</error></error> extends Foo {}
println(new Foo())
@@ -1,15 +1,15 @@
class <error descr="Cyclic inheritance involving 'A'">A</error> extends C {
class <error descr="Method 'invokeMethod' is not implemented"><error descr="Cyclic inheritance involving 'A'">A</error></error> extends C {
}
class <error descr="Cyclic inheritance involving 'B'">B</error> extends A {
class <error descr="Method 'invokeMethod' is not implemented"><error descr="Cyclic inheritance involving 'B'">B</error></error> extends A {
}
class <error descr="Cyclic inheritance involving 'C'">C</error> extends B {
class <error descr="Method 'invokeMethod' is not implemented"><error descr="Cyclic inheritance involving 'C'">C</error></error> extends B {
}
class <error descr="Cyclic inheritance involving 'B'">D</error> extends B {
class <error descr="Method 'invokeMethod' is not implemented"><error descr="Cyclic inheritance involving 'B'">D</error></error> extends B {
}