diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/constructors/GroovyGenerationInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/constructors/GroovyGenerationInfo.java index 182279a888d7..24370e5eecd1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/constructors/GroovyGenerationInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/constructors/GroovyGenerationInfo.java @@ -40,8 +40,10 @@ public class GroovyGenerationInfo 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 diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 2a06c2a18cda..8eb80f2a1c01 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -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 collection = GroovyOverrideImplementUtil.getMethodsToImplement(typeDefinition); + Collection collection = OverrideImplementUtil.getMethodsToOverrideImplement(typeDefinition, true); if (collection.isEmpty()) return; final PsiElement element = collection.iterator().next().getElement(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java index f89f4877b86b..4d1de8735242 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java @@ -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 collection = GroovyOverrideImplementUtil.getMethodsToImplement(anonymous); + final Collection collection = OverrideImplementUtil.getMethodsToOverrideImplement(anonymous, true); for (CandidateInfo info : collection) { myMethodToBodyMap.put((PsiMethod)info.getElement(), Collections.emptyList()); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java index 53ee710edffa..80fdaeff1a5d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java @@ -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) ; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrStatement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrStatement.java index 1407c6f5b68d..54b31ea3db20 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrStatement.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrStatement.java @@ -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 replaceWithStatement (T statement); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrCodeBlock.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrCodeBlock.java index 2c6ab42266ca..c321f5e9bf5c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrCodeBlock.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrCodeBlock.java @@ -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(); - } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrOpenBlock.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrOpenBlock.java index 0b0a27b833b5..70c788aaa271 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrOpenBlock.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrOpenBlock.java @@ -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 */ diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index 93d45de6af50..16b54849c8ab 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -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 diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java index 5f388f3042c2..427508551054 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java @@ -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); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java index 8cfa22545c97..8aba507a847c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java @@ -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 implements GrMethod, StubBasedPsiElement { + private static final Key> 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 i @Nullable public PsiCodeBlock getBody() { - return null; + final GrOpenBlock block = getBlock(); + if (block == null) return null; + + final SoftReference 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(newBody)); + return newBody; } public boolean isConstructor() { @@ -499,4 +512,4 @@ public abstract class GrMethodBaseImpl extends GrStubElementBase i public boolean isEquivalentTo(PsiElement another) { return PsiClassImplUtil.isMethodEquivalentTo(this, another); } -} \ No newline at end of file +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticCodeBlock.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticCodeBlock.java new file mode 100644 index 000000000000..69cc8fe0945e --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticCodeBlock.java @@ -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> 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 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(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(); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/JavaIdentifier.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/JavaIdentifier.java index 926eaf39aead..16c692d1417f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/JavaIdentifier.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/JavaIdentifier.java @@ -70,5 +70,8 @@ public class JavaIdentifier extends LightIdentifier { return myElement.getNextSibling(); } - + @Override + public PsiElement copy() { + return new JavaIdentifier(myManager, myElement); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightJavaToken.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightJavaToken.java new file mode 100644 index 000000000000..c0369f651b2e --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/LightJavaToken.java @@ -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; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyImplementMethodsHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyImplementMethodsHandler.java index bc0ac3d87342..e860d5681fa6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyImplementMethodsHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyImplementMethodsHandler.java @@ -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() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java index 309c27a75db7..5193b46f0b8b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java @@ -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 candidates = getMethodsToOverrideImplement(aClass, isImplement); - Collection secondary = isImplement ? Collections.emptyList() : getMethodsToOverrideImplement(aClass, !isImplement); + Collection candidates = OverrideImplementUtil.getMethodsToOverrideImplement(aClass, isImplement); + Collection secondary = isImplement ? Collections.emptyList() : OverrideImplementUtil.getMethodsToOverrideImplement(aClass, !isImplement); - MemberChooser chooser = OverrideImplementUtil.showOverrideImplementChooser(editor, aClass, isImplement, candidates, secondary); + final MemberChooser chooser = OverrideImplementUtil.showOverrideImplementChooser(editor, aClass, isImplement, candidates, secondary); if (chooser == null) return; final List 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 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 typeParameters = new ArrayList(); @@ -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 getMethodsToImplement(PsiClass typeDefinition) { - Collection methodsToImplement = OverrideImplementUtil.getMethodsToOverrideImplement(typeDefinition, true); - methodsToImplement = ContainerUtil.findAll(methodsToImplement, new Condition() { - public boolean value(CandidateInfo candidateInfo) { - //noinspection ConstantConditions - return !GroovyCommonClassNames.DEFAULT_BASE_CLASS_NAME - .equals(((PsiMethod)candidateInfo.getElement()).getContainingClass().getQualifiedName()); - } - }); - return methodsToImplement; - } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideMethodsHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideMethodsHandler.java index 488db60a0011..734fe8ac33cb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideMethodsHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideMethodsHandler.java @@ -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() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy index 096846f261d0..88fa177849ac 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy @@ -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() diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/overriding/GroovyOverrideImplementTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/overriding/GroovyOverrideImplementTest.groovy index f4c22de7500f..f5fa9012259b 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/overriding/GroovyOverrideImplementTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/overriding/GroovyOverrideImplementTest.groovy @@ -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 { } 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() } }); diff --git a/plugins/groovy/testdata/generate/ConstructorAtEnd_after.groovy b/plugins/groovy/testdata/generate/ConstructorAtEnd_after.groovy index 12ace68bc511..c460aac20f4f 100644 --- a/plugins/groovy/testdata/generate/ConstructorAtEnd_after.groovy +++ b/plugins/groovy/testdata/generate/ConstructorAtEnd_after.groovy @@ -4,6 +4,6 @@ class ConstructorAtEnd { } - ConstructorAtEnd() { + ConstructorAtEnd() { } } \ No newline at end of file diff --git a/plugins/groovy/testdata/generate/ConstructorAtOffset_after.groovy b/plugins/groovy/testdata/generate/ConstructorAtOffset_after.groovy index e3ffdd0a1b06..ee7aac2a9032 100644 --- a/plugins/groovy/testdata/generate/ConstructorAtOffset_after.groovy +++ b/plugins/groovy/testdata/generate/ConstructorAtOffset_after.groovy @@ -4,7 +4,7 @@ class ConstructorAtOffset { } - ConstructorAtOffset() { + ConstructorAtOffset() { } def bar() { diff --git a/plugins/groovy/testdata/generate/LonelyConstructor_after.groovy b/plugins/groovy/testdata/generate/LonelyConstructor_after.groovy index a5dabc6ad5c3..0b53ceded7c1 100644 --- a/plugins/groovy/testdata/generate/LonelyConstructor_after.groovy +++ b/plugins/groovy/testdata/generate/LonelyConstructor_after.groovy @@ -1,5 +1,5 @@ class LonelyConstructor { - LonelyConstructor() { + LonelyConstructor() { } } \ No newline at end of file diff --git a/plugins/groovy/testdata/highlighting/CircularInheritance.groovy b/plugins/groovy/testdata/highlighting/CircularInheritance.groovy index ebbc607cec60..11723cf25c99 100644 --- a/plugins/groovy/testdata/highlighting/CircularInheritance.groovy +++ b/plugins/groovy/testdata/highlighting/CircularInheritance.groovy @@ -1,4 +1,4 @@ -class Foo extends Bar {} -class Bar extends Foo {} +class Foo extends Bar {} +class Bar extends Foo {} println(new Foo()) \ No newline at end of file diff --git a/plugins/groovy/testdata/highlighting/CyclicInheritance.groovy b/plugins/groovy/testdata/highlighting/CyclicInheritance.groovy index 79936c6ea806..3f8adc194ebd 100644 --- a/plugins/groovy/testdata/highlighting/CyclicInheritance.groovy +++ b/plugins/groovy/testdata/highlighting/CyclicInheritance.groovy @@ -1,15 +1,15 @@ -class A extends C { +class A extends C { } -class B extends A { +class B extends A { } -class C extends B { +class C extends B { } -class D extends B { +class D extends B { } \ No newline at end of file