diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java index 4a5e3fbde661..87abba067121 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java @@ -895,7 +895,7 @@ public class ExtractMethodProcessor implements MatchProvider { protected PsiElement addToMethodCallLocation(PsiStatement statement) throws IncorrectOperationException { if (myEnclosingBlockStatement == null) { - PsiElement containingStatement = PsiTreeUtil.getParentOfType(myExpression != null ? myExpression : myElements[0], PsiStatement.class, false); + PsiElement containingStatement = myElements[0] instanceof PsiComment ? myElements[0] : PsiTreeUtil.getParentOfType(myExpression != null ? myExpression : myElements[0], PsiStatement.class, false); if (containingStatement == null) { containingStatement = PsiTreeUtil.getParentOfType(myExpression != null ? myExpression : myElements[0], PsiComment.class, false); } diff --git a/java/java-tests/testData/refactoring/extractMethod/ExtractWithLeadingComment.java b/java/java-tests/testData/refactoring/extractMethod/ExtractWithLeadingComment.java new file mode 100644 index 000000000000..a2519de1d143 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/ExtractWithLeadingComment.java @@ -0,0 +1,12 @@ +class Test { + public void method2() { + if (true) { + + // add to list2 + list2.add(true); + + } else { + + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/ExtractWithLeadingComment_after.java b/java/java-tests/testData/refactoring/extractMethod/ExtractWithLeadingComment_after.java new file mode 100644 index 000000000000..8833a288035d --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/ExtractWithLeadingComment_after.java @@ -0,0 +1,16 @@ +class Test { + public void method2() { + if (true) { + newMethod(); + + + } else { + + } + } + + private void newMethod() { + // add to list2 + list2.add(true); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java index 9d632414afb4..f6ad0d3b6b46 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java @@ -482,6 +482,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { doTest(); } + public void testExtractWithLeadingComment() throws Exception { + doTest(); + } + private void doPrepareErrorTest(final String expectedMessage) throws Exception { String expectedError = null; try { diff --git a/platform/lang-api/src/com/intellij/refactoring/util/MoveRenameUsageInfo.java b/platform/lang-api/src/com/intellij/refactoring/util/MoveRenameUsageInfo.java index 29a9ad83bc44..8015da154fff 100644 --- a/platform/lang-api/src/com/intellij/refactoring/util/MoveRenameUsageInfo.java +++ b/platform/lang-api/src/com/intellij/refactoring/util/MoveRenameUsageInfo.java @@ -29,7 +29,6 @@ public class MoveRenameUsageInfo extends UsageInfo{ private PsiReference myReference; private RangeMarker myReferenceRangeMarker = null; - private boolean myDynamicUsage; public MoveRenameUsageInfo(PsiReference reference, PsiElement referencedElement){ this(reference.getElement(), reference, referencedElement); @@ -46,12 +45,6 @@ public class MoveRenameUsageInfo extends UsageInfo{ init(element, reference, referencedElement); } - public MoveRenameUsageInfo(PsiElement element, PsiReference reference, int startOffset, int endOffset, PsiElement referencedElement, boolean nonCodeUsage, boolean isDynamicUsage){ - super(element, startOffset, endOffset, nonCodeUsage); - myDynamicUsage = isDynamicUsage; - init(element, reference, referencedElement); - } - private void init(final PsiElement element, PsiReference reference, final PsiElement referencedElement) { final Project project = element.getProject(); myReferencedElement = referencedElement; @@ -68,6 +61,7 @@ public class MoveRenameUsageInfo extends UsageInfo{ int elementStart = reference.getElement().getTextRange().getStartOffset(); myReferenceRangeMarker = document.createRangeMarker(elementStart + reference.getRangeInElement().getStartOffset(), elementStart + reference.getRangeInElement().getEndOffset()); + myDynamicUsage = reference.resolve() == null; } } @@ -99,8 +93,4 @@ public class MoveRenameUsageInfo extends UsageInfo{ if (rangeInElement.getStartOffset() != start || rangeInElement.getEndOffset() != end) return null; return reference; } - - public boolean isDynamicUsage() { - return myDynamicUsage; - } } diff --git a/platform/lang-api/src/com/intellij/usageView/UsageInfo.java b/platform/lang-api/src/com/intellij/usageView/UsageInfo.java index 425b01cc2929..23c9adee35b6 100644 --- a/platform/lang-api/src/com/intellij/usageView/UsageInfo.java +++ b/platform/lang-api/src/com/intellij/usageView/UsageInfo.java @@ -37,6 +37,7 @@ public class UsageInfo { private final int endOffset; // in navigation element public final boolean isNonCodeUsage; + protected boolean myDynamicUsage = false; public UsageInfo(@NotNull PsiElement element, int startOffset, int endOffset, boolean isNonCodeUsage) { LOG.assertTrue(element.isValid(), element); @@ -80,6 +81,7 @@ public class UsageInfo { public UsageInfo(@NotNull PsiReference reference) { this(reference.getElement(), reference.getRangeInElement().getStartOffset(), reference.getRangeInElement().getEndOffset()); + myDynamicUsage = reference.resolve() == null; } public UsageInfo(@NotNull PsiQualifiedReference reference) { @@ -206,4 +208,8 @@ public class UsageInfo { public void dispose() { ((Disposable)mySmartPointer).dispose(); } + + public boolean isDynamicUsage() { + return myDynamicUsage; + } } diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java index 57f760abbde8..5bff937c484d 100644 --- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java +++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java @@ -389,8 +389,7 @@ public class FindUsagesManager implements JDOMExternalizable { }); PsiManager.getInstance(project).getSearchHelper().processRequests(options.fastTrack, new ReadActionProcessor() { public boolean processInReadAction(final PsiReference ref) { - TextRange rangeInElement = ref.getRangeInElement(); - return usageInfoProcessor.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false)); + return usageInfoProcessor.process(new UsageInfo(ref)); } }); } diff --git a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java index a4d2f5012b6f..0238e016a128 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java @@ -117,18 +117,29 @@ public class TextEditorPsiDataProvider implements EditorDataProvider { } private static Language getLanguageAtCurrentPositionInEditor(final Editor editor, final PsiFile psiFile) { - int mostProbablyCorrectLanguageOffset = getOffset(editor); + final SelectionModel selectionModel = editor.getSelectionModel(); + int caretOffset = editor.getCaretModel().getOffset(); + int mostProbablyCorrectLanguageOffset = caretOffset == selectionModel.getSelectionStart() || + caretOffset == selectionModel.getSelectionEnd() + ? selectionModel.getSelectionStart() + : caretOffset; + if (selectionModel.hasSelection()) { + return getLanguageAtOffset(psiFile, mostProbablyCorrectLanguageOffset, selectionModel.getSelectionEnd()); + } return PsiUtilBase.getLanguageAtOffset(psiFile, mostProbablyCorrectLanguageOffset); } - private static int getOffset(Editor editor) { - final SelectionModel selectionModel = editor.getSelectionModel(); - int caretOffset = editor.getCaretModel().getOffset(); - return caretOffset == selectionModel.getSelectionStart() || - caretOffset == selectionModel.getSelectionEnd() - ? selectionModel.getSelectionStart() - : caretOffset; + private static Language getLanguageAtOffset(PsiFile psiFile, int mostProbablyCorrectLanguageOffset, int end) { + final PsiElement elt = psiFile.findElementAt(mostProbablyCorrectLanguageOffset); + if (elt == null) return psiFile.getLanguage(); + if (elt instanceof PsiWhiteSpace) { + final int incremented = elt.getTextRange().getEndOffset() + 1; + if (incremented <= end) { + return getLanguageAtOffset(psiFile, incremented, end); + } + } + return PsiUtilBase.findLanguageFromElement(elt); } @Nullable diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java index a942123ce3d8..ee01fe58425c 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java @@ -71,10 +71,9 @@ public class RenameUtil { continue; } PsiElement referenceElement = ref.getElement(); - final boolean isDynamic = ref.resolve() == null; result.add(new MoveRenameUsageInfo(referenceElement, ref, ref.getRangeInElement().getStartOffset(), ref.getRangeInElement().getEndOffset(), element, - isDynamic, isDynamic)); + ref.resolve() == null)); } processor.findCollisions(element, newName, allRenames, result); diff --git a/platform/usageView/src/com/intellij/usages/impl/rules/NonCodeUsageGroupingRule.java b/platform/usageView/src/com/intellij/usages/impl/rules/NonCodeUsageGroupingRule.java index 9663d13c773a..15cb1337d60f 100644 --- a/platform/usageView/src/com/intellij/usages/impl/rules/NonCodeUsageGroupingRule.java +++ b/platform/usageView/src/com/intellij/usages/impl/rules/NonCodeUsageGroupingRule.java @@ -18,6 +18,7 @@ package com.intellij.usages.impl.rules; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FileStatus; import com.intellij.refactoring.util.MoveRenameUsageInfo; +import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewBundle; import com.intellij.usages.Usage; import com.intellij.usages.UsageGroup; @@ -25,6 +26,7 @@ import com.intellij.usages.UsageInfo2UsageAdapter; import com.intellij.usages.UsageView; import com.intellij.usages.rules.PsiElementUsage; import com.intellij.usages.rules.UsageGroupingRule; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -90,10 +92,17 @@ public class NonCodeUsageGroupingRule implements UsageGroupingRule { private static class DynamicUsageGroup implements UsageGroup { public static final UsageGroup INSTANCE = new DynamicUsageGroup(); + @NonNls private static final String DYNAMIC_CAPTION = "Dynamic usages"; @NotNull public String getText(UsageView view) { - return view == null ? "Dynamic usages" : view.getPresentation().getDynamicCodeUsagesString(); + if (view == null) { + return DYNAMIC_CAPTION; + } + else { + final String dynamicCodeUsagesString = view.getPresentation().getDynamicCodeUsagesString(); + return dynamicCodeUsagesString == null ? DYNAMIC_CAPTION : dynamicCodeUsagesString; + } } public void update() { @@ -117,15 +126,13 @@ public class NonCodeUsageGroupingRule implements UsageGroupingRule { public UsageGroup groupUsage(Usage usage) { if (usage instanceof PsiElementUsage) { - if (((PsiElementUsage)usage).isNonCodeUsage()) { - if (usage instanceof UsageInfo2UsageAdapter) { - if (((UsageInfo2UsageAdapter)usage).getUsageInfo() instanceof MoveRenameUsageInfo) { - final MoveRenameUsageInfo usageInfo = (MoveRenameUsageInfo)((UsageInfo2UsageAdapter)usage).getUsageInfo(); - if (usageInfo.isDynamicUsage()) { - return DynamicUsageGroup.INSTANCE; - } - } + if (usage instanceof UsageInfo2UsageAdapter) { + final UsageInfo usageInfo = ((UsageInfo2UsageAdapter)usage).getUsageInfo(); + if (usageInfo.isDynamicUsage()) { + return DynamicUsageGroup.INSTANCE; } + } + if (((PsiElementUsage)usage).isNonCodeUsage()) { return NonCodeUsageGroup.INSTANCE; } else { diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 3c69d065228d..d90bdad173ef 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -260,7 +260,6 @@ - diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GroovyUsageViewGroupingRuleProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GroovyUsageViewGroupingRuleProvider.java deleted file mode 100644 index cbdb3eee86ca..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GroovyUsageViewGroupingRuleProvider.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2000-2009 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.findUsages; - -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.project.Project; -import com.intellij.usages.UsageView; -import com.intellij.usages.rules.UsageGroupingRule; -import com.intellij.usages.rules.UsageGroupingRuleProvider; -import org.jetbrains.annotations.NotNull; - -/** - * @author ven - */ -public class GroovyUsageViewGroupingRuleProvider implements UsageGroupingRuleProvider { - @NotNull - public UsageGroupingRule[] getActiveRules(Project project) { - return new UsageGroupingRule[] {new LateBoundUsageGroupingRule()}; - } - - @NotNull - public AnAction[] createGroupingActions(UsageView view) { - return AnAction.EMPTY_ARRAY; - } -} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LateBoundUsageGroupingRule.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LateBoundUsageGroupingRule.java deleted file mode 100644 index 5d02dfed9ca6..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LateBoundUsageGroupingRule.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2000-2009 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.findUsages; - -import com.intellij.openapi.vcs.FileStatus; -import com.intellij.psi.PsiElement; -import com.intellij.usages.Usage; -import com.intellij.usages.UsageGroup; -import com.intellij.usages.UsageView; -import com.intellij.usages.rules.OrderableUsageGroupingRule; -import com.intellij.usages.rules.PsiElementUsage; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; - -import javax.swing.*; - -/** - * @author ven - */ -public class LateBoundUsageGroupingRule implements OrderableUsageGroupingRule { - private final LateBoundGroup INSTANCE = new LateBoundGroup(); - - private class LateBoundGroup implements UsageGroup { - - public Icon getIcon(boolean isOpen) { - return null; - } - - @NotNull - public String getText(UsageView view) { - return "Dynamically typed usages"; - } - - public FileStatus getFileStatus() { - return null; - } - - public boolean isValid() { - return true; - } - - public void update() { - } - - public int compareTo(UsageGroup usageGroup) { - return getText(null).compareTo(usageGroup.getText(null)); - } - - public void navigate(boolean b) { - } - - public boolean canNavigate() { - return false; - } - - public boolean canNavigateToSource() { - return false; - } - } - - public UsageGroup groupUsage(Usage usage) { - if (usage instanceof PsiElementUsage) { - final PsiElement element = ((PsiElementUsage) usage).getElement(); - if (element instanceof GrReferenceExpression && ((GrReferenceExpression) element).resolve() == null) { - return INSTANCE; - } - } - - return null; - } - - public int getRank() { - return 0; - } -} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java index 8f3d84c4894e..f2449cd6e89f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java @@ -440,12 +440,16 @@ public class GroovyParameterInfoHandler implements ParameterInfoHandler im return findChildByType(TokenSets.VISIBILITY_MODIFIERS) != null; } - public boolean hasModifierProperty(@NotNull @NonNls String modifier) { - final PsiElement parent = getParent(); + public static boolean checkModifierProperty(@NotNull GrModifierList modifierList, @NotNull String modifier) { + final PsiElement parent = modifierList.getParent(); if (parent instanceof GrVariableDeclaration && parent.getParent() instanceof GrTypeDefinitionBody) { PsiElement pParent = parent.getParent().getParent(); - if (!hasExplicitVisibilityModifiers()) { //properties are backed by private fields + if (!modifierList.hasExplicitVisibilityModifiers()) { //properties are backed by private fields if (!(pParent instanceof PsiClass) || !((PsiClass)pParent).isInterface()) { if (modifier.equals(GrModifier.PRIVATE)) return true; if (modifier.equals(GrModifier.PROTECTED)) return false; @@ -161,20 +161,20 @@ public class GrModifierListImpl extends GrStubElementBase im if (modifier.equals(GrModifier.FINAL)) return true; } if (pParent instanceof GrTypeDefinition) { - PsiModifierList modifierList = ((GrTypeDefinition)pParent).getModifierList(); - if (modifierList != null && modifierList.findAnnotation(GroovyImmutableAnnotationInspection.IMMUTABLE) != null) { + PsiModifierList pModifierList = ((GrTypeDefinition)pParent).getModifierList(); + if (pModifierList != null && pModifierList.findAnnotation(GroovyImmutableAnnotationInspection.IMMUTABLE) != null) { if (modifier.equals(GrModifier.FINAL)) return true; } } } - if (hasExplicitModifier(modifier)) { + if (modifierList.hasExplicitModifier(modifier)) { return true; } if (modifier.equals(GrModifier.PUBLIC)) { //groovy type definitions and methods are public by default - return !hasExplicitModifier(GrModifier.PRIVATE) && !hasExplicitModifier(GrModifier.PROTECTED); + return !modifierList.hasExplicitModifier(GrModifier.PRIVATE) && !modifierList.hasExplicitModifier(GrModifier.PROTECTED); } if (parent instanceof GrTypeDefinition) { @@ -190,6 +190,10 @@ public class GrModifierListImpl extends GrStubElementBase im return false; } + public boolean hasModifierProperty(@NotNull @NonNls String modifier) { + return checkModifierProperty(this, modifier); + } + public boolean hasExplicitModifier(@NotNull @NonNls String name) { final GrModifierListStub stub = getStub(); if (stub != null) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterListImpl.java index 0299e6dfcd5d..a3f465a9c8c0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterListImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterListImpl.java @@ -98,8 +98,9 @@ public class GrParameterListImpl extends GrStubElementBase implements } public int getParameterNumber(final GrParameter parameter) { - for (int i = 0; i < getParameters().length; i++) { - GrParameter param = getParameters()[i]; + GrParameter[] parameters = getParameters(); + for (int i = 0; i < parameters.length; i++) { + GrParameter param = parameters[i]; if (param == parameter) { return i; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightMethodBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightMethodBuilder.java new file mode 100644 index 000000000000..d5deb15634a9 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightMethodBuilder.java @@ -0,0 +1,379 @@ +/* + * 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.navigation.ItemPresentation; +import com.intellij.psi.*; +import com.intellij.psi.impl.ElementPresentationUtil; +import com.intellij.psi.impl.PsiClassImplUtil; +import com.intellij.psi.impl.PsiImplUtil; +import com.intellij.psi.impl.PsiSuperMethodImplUtil; +import com.intellij.psi.impl.light.LightElement; +import com.intellij.psi.impl.light.LightEmptyImplementsList; +import com.intellij.psi.impl.light.LightIdentifier; +import com.intellij.psi.presentation.java.JavaPresentationUtil; +import com.intellij.psi.search.SearchScope; +import com.intellij.psi.util.MethodSignature; +import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; +import com.intellij.ui.RowIcon; +import com.intellij.util.ArrayUtil; +import com.intellij.util.Icons; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.GroovyFileType; +import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment; +import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; +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.api.statements.params.GrParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; + +import javax.swing.*; +import java.util.List; + +/** + * @author Sergey Evdokimov + */ +public class GrLightMethodBuilder extends LightElement implements GrMethod { + private final String myName; + private PsiType myReturnType; + private final GrModifierList myModifierList; + private GrParameterList myParameterList; + private Icon myBaseIcon; + private PsiClass myContainingClass; + private Object myMethodKind; + private String[] namedParametersArray = ArrayUtil.EMPTY_STRING_ARRAY; + + public GrLightMethodBuilder(PsiManager manager, String name) { + this(manager, name, new GrLightParameterListBuilder(manager, GroovyFileType.GROOVY_LANGUAGE), null); + } + + public GrLightMethodBuilder(PsiManager manager, + String name, + GrParameterList parameterList, + GrModifierList modifierList) { + super(manager, GroovyFileType.GROOVY_LANGUAGE); + myName = name; + myParameterList = parameterList; + myModifierList = modifierList == null ? new GrLightModifierList(this, ArrayUtil.EMPTY_STRING_ARRAY) : modifierList; + } + + public void setNamedParametersArray(@NotNull String[] namedParametersArray) { + this.namedParametersArray = namedParametersArray; + } + + @Override + public ItemPresentation getPresentation() { + return JavaPresentationUtil.getMethodPresentation(this); + } + + public boolean hasTypeParameters() { + return false; + } + + @NotNull + public PsiTypeParameter[] getTypeParameters() { + return PsiTypeParameter.EMPTY_ARRAY; + } + + public PsiTypeParameterList getTypeParameterList() { + //todo + return null; + } + + public GrDocComment getDocComment() { + //todo + return null; + } + + public boolean isDeprecated() { + //todo + return false; + } + + public PsiElement setName(@NotNull String name) throws IncorrectOperationException { + throw new IncorrectOperationException("Please don't rename light methods"); + } + + @NotNull + public String getName() { + return myName; + } + + @NotNull + public HierarchicalMethodSignature getHierarchicalMethodSignature() { + return PsiSuperMethodImplUtil.getHierarchicalMethodSignature(this); + } + + public boolean hasModifierProperty(@NotNull String name) { + return getModifierList().hasModifierProperty(name); + } + + @Override + public GrMember[] getMembers() { + return GrMember.EMPTY_ARRAY; + } + + @NotNull + public GrModifierList getModifierList() { + return myModifierList; + } + + @NotNull + @Override + public String[] getNamedParametersArray() { + return namedParametersArray; + } + + public GrLightMethodBuilder addModifiers(String... modifiers) { + for (String modifier : modifiers) { + addModifier(modifier); + } + return this; + } + + public GrLightMethodBuilder addModifier(String modifier) { + ((GrLightModifierList)myModifierList).addModifier(modifier); + return this; + } + + public GrLightMethodBuilder setModifiers(String[] modifiers) { + ((GrLightModifierList)myModifierList).clearModifiers(); + addModifiers(modifiers); + return this; + } + + @Override + public GrOpenBlock getBlock() { + return null; + } + + @Override + public void setBlock(GrCodeBlock newBlock) { + throw new IncorrectOperationException(); + } + + @Override + public GrTypeElement getReturnTypeElementGroovy() { + return null; + } + + @Override + public PsiType getInferredReturnType() { + return getReturnType(); + } + + public PsiType getReturnType() { + return myReturnType; + } + + public GrTypeElement setReturnType(PsiType returnType) { + myReturnType = returnType; + return null; + } + + public PsiTypeElement getReturnTypeElement() { + return null; + } + + @Override + public GrParameter[] getParameters() { + return myParameterList.getParameters(); + } + + @NotNull + public GrParameterList getParameterList() { + return myParameterList; + } + + public GrLightMethodBuilder addParameter(@NotNull GrParameter parameter) { + ((GrLightParameterListBuilder)myParameterList).addParameter(parameter); + return this; + } + + public GrLightMethodBuilder addParameter(@NotNull String name, @NotNull String type, boolean isOptional) { + return addParameter(name, JavaPsiFacade.getElementFactory(getProject()).createTypeFromText(type, this), isOptional); + } + + public GrLightMethodBuilder addParameter(@NotNull String name, @NotNull PsiType type, boolean isOptional) { + GrLightParameter param = new GrLightParameter(name, type, this).setOptional(isOptional); + return addParameter(param); + } + + @NotNull + public PsiReferenceList getThrowsList() { + //todo + return new LightEmptyImplementsList(getManager()); + } + + public PsiCodeBlock getBody() { + return null; + } + + @Override + public boolean isConstructor() { + return false; + } + + public boolean isVarArgs() { + //todo + return false; + } + + @NotNull + public MethodSignature getSignature(@NotNull PsiSubstitutor substitutor) { + return MethodSignatureBackedByPsiMethod.create(this, substitutor); + } + + public PsiIdentifier getNameIdentifier() { + return null; + } + + @NotNull + public PsiMethod[] findSuperMethods() { + return PsiSuperMethodImplUtil.findSuperMethods(this); + } + + @NotNull + public PsiMethod[] findSuperMethods(boolean checkAccess) { + return PsiSuperMethodImplUtil.findSuperMethods(this, checkAccess); + } + + @NotNull + public PsiMethod[] findSuperMethods(PsiClass parentClass) { + return PsiSuperMethodImplUtil.findSuperMethods(this, parentClass); + } + + @NotNull + public List findSuperMethodSignaturesIncludingStatic(boolean checkAccess) { + return PsiSuperMethodImplUtil.findSuperMethodSignaturesIncludingStatic(this, checkAccess); + } + + public PsiMethod findDeepestSuperMethod() { + return PsiSuperMethodImplUtil.findDeepestSuperMethod(this); + } + + @NotNull + public PsiMethod[] findDeepestSuperMethods() { + return PsiSuperMethodImplUtil.findDeepestSuperMethods(this); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JavaElementVisitor) { + ((JavaElementVisitor)visitor).visitMethod(this); + } + } + + public GrLightMethodBuilder setNavigationElement(PsiElement navigationElement) { + super.setNavigationElement(navigationElement); + return this; + } + + public PsiClass getContainingClass() { + return myContainingClass; + } + + public GrLightMethodBuilder setContainingClass(PsiClass containingClass) { + myContainingClass = containingClass; + return this; + } + + public GrLightMethodBuilder setMethodKind(@Nullable Object debugKindName) { + myMethodKind = debugKindName; + return this; + } + + @NotNull + @Override + public PsiElement getNameIdentifierGroovy() { + return new LightIdentifier(getManager(), getName()); + } + + @Override + public void accept(GroovyElementVisitor visitor) { + + } + + @Override + public void acceptChildren(GroovyElementVisitor visitor) { + + } + + public static boolean checkKind(@Nullable PsiElement method, @NotNull Object kind) { + return method instanceof GrLightMethodBuilder && kind.equals(((GrLightMethodBuilder)method).myMethodKind); + } + + public String toString() { + return myMethodKind + ":" + getName(); + } + + public Icon getElementIcon(final int flags) { + Icon methodIcon = myBaseIcon != null ? myBaseIcon : + hasModifierProperty(PsiModifier.ABSTRACT) ? Icons.ABSTRACT_METHOD_ICON : Icons.METHOD_ICON; + RowIcon baseIcon = createLayeredIcon(methodIcon, ElementPresentationUtil.getFlags(this, false)); + return ElementPresentationUtil.addVisibilityIcon(this, flags, baseIcon); + } + + public GrLightMethodBuilder setBaseIcon(Icon baseIcon) { + myBaseIcon = baseIcon; + return this; + } + + @Override + public boolean isEquivalentTo(final PsiElement another) { + return PsiClassImplUtil.isMethodEquivalentTo(this, another); + } + + @NotNull + public SearchScope getUseScope() { + return PsiImplUtil.getMemberUseScope(this); + } + + @Override + @Nullable + public PsiFile getContainingFile() { + final PsiClass containingClass = getContainingClass(); + return containingClass == null ? null : containingClass.getContainingFile(); + } + + @Override + public PsiElement getContext() { + final PsiElement navElement = getNavigationElement(); + if (navElement != this) { + return navElement; + } + + final PsiClass cls = getContainingClass(); + if (cls != null) { + return cls; + } + + return getContainingFile(); + } + + public PsiMethodReceiver getMethodReceiver() { + return null; + } + public PsiType getReturnTypeNoResolve() { + return getReturnType(); + } + +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightModifierList.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightModifierList.java new file mode 100644 index 000000000000..214690a93918 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightModifierList.java @@ -0,0 +1,125 @@ +/* + * 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.psi.*; +import com.intellij.psi.impl.light.LightElement; +import com.intellij.util.ArrayUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierFlags; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; +import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.modifiers.GrModifierListImpl; + +public class GrLightModifierList extends LightElement implements GrModifierList { + + private String[] myModifiers; + + private final PsiElement myParent; + + public GrLightModifierList(@NotNull PsiElement parent, String[] modifiers) { + super(parent.getManager(), parent.getLanguage()); + myModifiers = modifiers; + myParent = parent; + } + + @Override + public PsiElement getParent() { + return myParent; + } + + public void addModifier(String modifier) { + myModifiers = ArrayUtil.append(myModifiers, modifier, ArrayUtil.STRING_ARRAY_FACTORY); + } + + public void clearModifiers() { + myModifiers = ArrayUtil.EMPTY_STRING_ARRAY; + } + + public boolean hasModifierProperty(@NotNull String name){ + return GrModifierListImpl.checkModifierProperty(this, name); + } + + public boolean hasExplicitModifier(@NotNull String name) { + return ArrayUtil.contains(name, myModifiers); + } + + public void setModifierProperty(@NotNull String name, boolean value) throws IncorrectOperationException{ + throw new IncorrectOperationException(); + } + + public void checkSetModifierProperty(@NotNull String name, boolean value) throws IncorrectOperationException{ + throw new IncorrectOperationException(); + } + + @NotNull + public GrAnnotation[] getAnnotations() { + return GrAnnotation.EMPTY_ARRAY; + } + + @NotNull + public PsiAnnotation[] getApplicableAnnotations() { + return getAnnotations(); + } + + public PsiAnnotation findAnnotation(@NotNull String qualifiedName) { + return null; + } + + @NotNull + public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) { + throw new IncorrectOperationException("Method addAnnotation is not yet implemented in " + getClass().getName()); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JavaElementVisitor) { + ((JavaElementVisitor)visitor).visitModifierList(this); + } + else { + visitor.visitElement(this); + } + } + + public String toString() { + return "GrModifierList"; + } + + @NotNull + public PsiElement[] getModifiers() { + return PsiElement.EMPTY_ARRAY; + } + + @Override + public boolean hasExplicitVisibilityModifiers() { + for (String modifier : myModifiers) { + if (modifier.equals(PsiModifier.PRIVATE) || modifier.equals(PsiModifier.PUBLIC) || modifier.equals(PsiModifier.PROTECTED)) return true; + } + return false; + } + + @Override + public void accept(GroovyElementVisitor visitor) { + visitor.visitModifierList(this); + } + + @Override + public void acceptChildren(GroovyElementVisitor visitor) { + + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightParameterListBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightParameterListBuilder.java new file mode 100644 index 000000000000..b883720ecf0a --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightParameterListBuilder.java @@ -0,0 +1,108 @@ +/* + * 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.lang.Language; +import com.intellij.psi.*; +import com.intellij.psi.impl.light.LightElement; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Sergey Evdokimov + */ +public class GrLightParameterListBuilder extends LightElement implements GrParameterList { + private final List myParameters = new ArrayList(); + private GrParameter[] myCachedParameters; + + public GrLightParameterListBuilder(PsiManager manager, Language language) { + super(manager, language); + } + + public void addParameter(GrParameter parameter) { + myParameters.add(parameter); + myCachedParameters = null; + } + + @Override + public String toString() { + return "GrLightParameterListBuilder"; + } + + @NotNull + @Override + public GrParameter[] getParameters() { + if (myCachedParameters == null) { + if (myParameters.isEmpty()) { + myCachedParameters = GrParameter.EMPTY_ARRAY; + } + else { + myCachedParameters = myParameters.toArray(new GrParameter[myParameters.size()]); + } + } + + return myCachedParameters; + } + + @Override + public void addParameterToEnd(GrParameter parameter) { + + } + + @Override + public void addParameterToHead(GrParameter parameter) { + throw new IncorrectOperationException("GrLightParameterListBuilder is unmodifiable"); + } + + @Override + public int getParameterNumber(GrParameter parameter) { + return getParameterIndex(parameter); + } + + @Override + public int getParameterIndex(PsiParameter parameter) { + //noinspection SuspiciousMethodCalls + return myParameters.indexOf(parameter); + } + + @Override + public int getParametersCount() { + return myParameters.size(); + } + + @Override + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JavaElementVisitor) { + ((JavaElementVisitor) visitor).visitParameterList(this); + } + } + + @Override + public void accept(GroovyElementVisitor visitor) { + visitor.visitParameterList(this); + } + + @Override + public void acceptChildren(GroovyElementVisitor visitor) { + + } +}