diff options
Diffstat (limited to 'java/java-impl/src/com/intellij')
37 files changed, 944 insertions, 257 deletions
diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java index 08a071231410..0bf1c1cd7218 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java @@ -31,7 +31,10 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.*; +import com.intellij.psi.util.PropertyUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.NullableFunction; import com.intellij.util.Processor; @@ -126,10 +129,6 @@ public class ExpectedTypesProvider { final boolean voidable, boolean usedAfter) { if (expr == null) return ExpectedTypeInfo.EMPTY_ARRAY; PsiElement parent = expr.getParent(); - while (parent instanceof PsiParenthesizedExpression) { - expr = (PsiExpression)parent; - parent = parent.getParent(); - } MyParentVisitor visitor = new MyParentVisitor(expr, forCompletion, classProvider, voidable, usedAfter); if (parent != null) { parent.accept(visitor); @@ -243,6 +242,25 @@ public class ExpectedTypesProvider { } @Override + public void visitParenthesizedExpression(PsiParenthesizedExpression expression) { + PsiElement parent = expression.getParent(); + if (parent != null) { + final MyParentVisitor visitor = new MyParentVisitor(expression, myForCompletion, myClassProvider, myVoidable, myUsedAfter); + parent.accept(visitor); + for (final ExpectedTypeInfo info : visitor.myResult) { + myResult.add(createInfoImpl(info.getType(), info.getKind(), info.getDefaultType(), TailTypes.RPARENTH, info.getCalledMethod(), + new NullableComputable<String>() { + @Nullable + @Override + public String compute() { + return ((ExpectedTypeInfoImpl)info).getExpectedName(); + } + })); + } + } + } + + @Override public void visitAnnotationMethod(@NotNull final PsiAnnotationMethod method) { if (myExpr == method.getDefaultValue()) { final PsiType type = method.getReturnType(); diff --git a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsLineMarkerProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsLineMarkerProvider.java index e373207222ea..8605a8f91a83 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsLineMarkerProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsLineMarkerProvider.java @@ -51,14 +51,14 @@ public class ExternalAnnotationsLineMarkerProvider implements LineMarkerProvider if (!(element instanceof PsiModifierListOwner)) return null; if (element instanceof PsiParameter || element instanceof PsiLocalVariable) return null; - if (!shouldShowSignature(preferCompiledElement((PsiModifierListOwner)element))) { + if (!shouldShowSignature((PsiModifierListOwner)element)) { return null; } final Function<PsiModifierListOwner, String> annotationsCollector = new Function<PsiModifierListOwner, String>() { @Override public String fun(PsiModifierListOwner owner) { - return XmlStringUtil.wrapInHtml(JavaDocInfoGenerator.generateSignature(preferCompiledElement(owner))); + return XmlStringUtil.wrapInHtml(JavaDocInfoGenerator.generateSignature(owner)); } }; return new LineMarkerInfo<PsiModifierListOwner>((PsiModifierListOwner)element, element.getTextOffset(), AllIcons.Gutter.ExtAnnotation, @@ -67,11 +67,6 @@ public class ExternalAnnotationsLineMarkerProvider implements LineMarkerProvider GutterIconRenderer.Alignment.LEFT); } - private static PsiModifierListOwner preferCompiledElement(PsiModifierListOwner element) { - PsiElement original = element.getOriginalElement(); - return original instanceof PsiModifierListOwner ? (PsiModifierListOwner)original : element; - } - private static boolean shouldShowSignature(PsiModifierListOwner owner) { if (hasNonCodeAnnotations(owner)) { return true; @@ -111,7 +106,7 @@ public class ExternalAnnotationsLineMarkerProvider implements LineMarkerProvider if (ref == null) return true; PsiElement target = ref.resolve(); - return !(target instanceof PsiClass) || JavaDocInfoGenerator.isDocumentedAnnotationType((PsiClass)target); + return !(target instanceof PsiClass) || JavaDocInfoGenerator.isDocumentedAnnotationType(target); } @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/TailTypes.java b/java/java-impl/src/com/intellij/codeInsight/TailTypes.java index 923dd8213019..244067bd3f36 100644 --- a/java/java-impl/src/com/intellij/codeInsight/TailTypes.java +++ b/java/java-impl/src/com/intellij/codeInsight/TailTypes.java @@ -28,6 +28,12 @@ public class TailTypes { return styleSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES && editor.getDocument().getCharsSequence().charAt(tailOffset - 1) != '('; } }; + public static final TailType RPARENTH = new RParenthTailType(){ + @Override + protected boolean isSpaceWithinParentheses(final CommonCodeStyleSettings styleSettings, final Editor editor, final int tailOffset) { + return styleSettings.SPACE_WITHIN_PARENTHESES; + } + }; public static final TailType IF_RPARENTH = new RParenthTailType(){ @Override protected boolean isSpaceWithinParentheses(final CommonCodeStyleSettings styleSettings, final Editor editor, final int tailOffset) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 8cc9d06aed04..112b243e0ea3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -544,7 +544,7 @@ public class JavaCompletionUtil { return JavaClassNameCompletionContributor.createClassLookupItems((PsiClass)completion, JavaClassNameCompletionContributor.AFTER_NEW.accepts(reference), JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER, - Condition.TRUE); + Conditions.<PsiClass>alwaysTrue()); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java index 2a9fc2f4a79f..978e5b24d2e8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -28,7 +28,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Conditions; import com.intellij.openapi.util.text.StringUtil; import com.intellij.patterns.PsiJavaPatterns; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; @@ -43,7 +43,10 @@ import com.intellij.psi.javadoc.*; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.util.*; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ProcessingContext; +import com.intellij.util.Processor; +import com.intellij.util.SystemProperties; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NonNls; @@ -81,7 +84,7 @@ public class JavaDocCompletionContributor extends CompletionContributor { if (ref instanceof PsiJavaReference) { result.stopHere(); - final JavaCompletionProcessor processor = new JavaCompletionProcessor(position, TrueFilter.INSTANCE, JavaCompletionProcessor.Options.CHECK_NOTHING, Condition.TRUE); + final JavaCompletionProcessor processor = new JavaCompletionProcessor(position, TrueFilter.INSTANCE, JavaCompletionProcessor.Options.CHECK_NOTHING, Conditions.<String>alwaysTrue()); ((PsiJavaReference) ref).processVariants(processor); for (final CompletionElement _item : processor.getResults()) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java index ad53d9484959..cc67ca51de58 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -20,6 +20,7 @@ import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementWeigher; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Conditions; import com.intellij.patterns.ElementPattern; import com.intellij.psi.*; import com.intellij.psi.filters.getters.MembersGetter; @@ -127,8 +128,7 @@ public class PreferByKindWeigher extends LookupElementWeigher { }; } - //noinspection unchecked - return Condition.FALSE; + return Conditions.alwaysFalse(); } enum MyResult { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java index dbf454207cca..d753875208c3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java @@ -333,6 +333,9 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction/*, Hig else { PsiType exprType = RefactoringUtil.getTypeByExpression(expression); if (exprType == null) return null; + if (exprType instanceof PsiDisjunctionType) { + exprType = ((PsiDisjunctionType)exprType).getLeastUpperBound(); + } final ParameterInfoImpl changedParameterInfo = new ParameterInfoImpl(i, parameter.getName(), exprType); result.add(changedParameterInfo); changedParams.add(changedParameterInfo); @@ -403,6 +406,9 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction/*, Hig if (varargParam != null && pi >= parameters.length) return false; PsiType exprType = RefactoringUtil.getTypeByExpression(expression); if (exprType == null) return false; + if (exprType instanceof PsiDisjunctionType) { + exprType = ((PsiDisjunctionType)exprType).getLeastUpperBound(); + } JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(expression.getProject()); String name = suggestUniqueParameterName(codeStyleManager, expression, exprType, existingNames); final ParameterInfoImpl newParameterInfo = new ParameterInfoImpl(-1, name, exprType, expression.getText().replace('\n', ' ')); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java index 8e93a6a0c817..ad3d3fc8010a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java @@ -182,7 +182,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix { context); } - protected static PsiMethod createMethod(PsiClass targetClass, + public static PsiMethod createMethod(PsiClass targetClass, PsiClass parentClass, PsiMember enclosingContext, String methodName) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateStaticMethodQuickFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateStaticMethodQuickFix.java new file mode 100644 index 000000000000..8268ee58d44a --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateStaticMethodQuickFix.java @@ -0,0 +1,81 @@ +package com.intellij.codeInsight.daemon.impl.quickfix; + +import com.intellij.codeInsight.ExpectedTypeInfo; +import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiUtil; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class CreateStaticMethodQuickFix implements LocalQuickFix { + @NotNull + private final PsiClass targetClass; + @NotNull + private final String methodName; + @NotNull + private final List<String> types; + + + public CreateStaticMethodQuickFix(@NotNull PsiClass aClass, + @NotNull String name, + @NotNull List<String> types) { + targetClass = aClass; + methodName = name; + this.types = types; + } + + + @NotNull + @Override + public String getName() { + return QuickFixBundle.message("create.method.from.usage.family"); + } + + @NotNull + @Override + public String getFamilyName() { + return QuickFixBundle.message("create.method.from.usage.family"); + } + + @Override + public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) { + boolean java8Interface = false; + if (targetClass.isInterface()) { + if (PsiUtil.isLanguageLevel8OrHigher(targetClass)) { + java8Interface = true; + } else { + return; + } + } + + PsiMethod method = CreateMethodFromUsageFix.createMethod(targetClass, null, null, methodName); + if (method == null) { + return; + } + + if (!java8Interface) { + PsiUtil.setModifierProperty(method, PsiModifier.PUBLIC, true); + } + PsiUtil.setModifierProperty(method, PsiModifier.STATIC, true); + + List<Pair<PsiExpression,PsiType>> args = ContainerUtil.map(types, new Function<String, Pair<PsiExpression, PsiType>>() { + @Override + public Pair<PsiExpression, PsiType> fun(String s) { + return new Pair<PsiExpression, PsiType>(null, PsiType.getTypeByName(s, project, GlobalSearchScope.allScope(project))); + } + }); + CreateMethodFromUsageFix.doCreate(targetClass, method, false, + args, + PsiSubstitutor.UNKNOWN, + ExpectedTypeInfo.EMPTY_ARRAY, + null); + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveClassToModuleFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveClassToModuleFix.java index d8caac1d59a6..9c1d38853b2c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveClassToModuleFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveClassToModuleFix.java @@ -42,12 +42,12 @@ import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.RefactoringActionHandlerFactory; import com.intellij.ui.components.JBList; import com.intellij.util.IncorrectOperationException; -import org.codehaus.groovy.util.ListHashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -55,7 +55,7 @@ import java.util.Map; * @author cdr */ public class MoveClassToModuleFix implements IntentionAction { - private final Map<PsiClass, Module> myModules = new ListHashMap<PsiClass, Module>(); + private final Map<PsiClass, Module> myModules = new LinkedHashMap<PsiClass, Module>(); private final String myReferenceName; private final Module myCurrentModule; private final PsiDirectory mySourceRoot; diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithTryFinallySurrounder.java b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithTryFinallySurrounder.java index e757ddeacc17..28732a65390b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithTryFinallySurrounder.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithTryFinallySurrounder.java @@ -19,10 +19,8 @@ import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.EditorModificationUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.util.IncorrectOperationException; @@ -65,16 +63,14 @@ class JavaWithTryFinallySurrounder extends JavaStatementsSurrounder{ if (finallyBlock == null) { return null; } - int offset = finallyBlock.getTextRange().getStartOffset() + 2; - editor.getCaretModel().moveToOffset(offset); - final Document document = editor.getDocument(); + Document document = editor.getDocument(); PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document); + TextRange finallyBlockRange = finallyBlock.getTextRange(); + int newLineOffset = finallyBlockRange.getStartOffset() + 2; + editor.getCaretModel().moveToOffset(newLineOffset); editor.getSelectionModel().removeSelection(); - final PsiStatement[] tryBlockStatements = tryBlock.getStatements(); - LOG.assertTrue(tryBlockStatements.length > 0, tryBlock.getText()); - final PsiStatement firstTryStmt = tryBlockStatements[0]; - final int indent = firstTryStmt.getTextOffset() - document.getLineStartOffset(document.getLineNumber(firstTryStmt.getTextOffset())); - EditorModificationUtil.insertStringAtCaret(editor, StringUtil.repeat(" ", indent), false, true); + CodeStyleManager.getInstance(project).adjustLineIndent(document, newLineOffset); + PsiDocumentManager.getInstance(project).commitDocument(document); return new TextRange(editor.getCaretModel().getOffset(), editor.getCaretModel().getOffset()); } }
\ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightExceptionsHandlerFactory.java b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightExceptionsHandlerFactory.java index c7bd10cc2b39..a1f206b4ba8e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightExceptionsHandlerFactory.java +++ b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightExceptionsHandlerFactory.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.ExceptionUtil; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Conditions; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -57,7 +58,7 @@ public class HighlightExceptionsHandlerFactory extends HighlightUsagesHandlerFac final PsiCodeBlock tryBlock = tryStatement.getTryBlock(); if (tryBlock == null) return null; final Collection<PsiClassType> psiClassTypes = ExceptionUtil.collectUnhandledExceptions(tryBlock, tryBlock); - return new HighlightExceptionsHandler(editor, file, target, psiClassTypes.toArray(new PsiClassType[psiClassTypes.size()]), tryBlock, Condition.TRUE); + return new HighlightExceptionsHandler(editor, file, target, psiClassTypes.toArray(new PsiClassType[psiClassTypes.size()]), tryBlock, Conditions.<PsiType>alwaysTrue()); } @Nullable @@ -112,6 +113,6 @@ public class HighlightExceptionsHandlerFactory extends HighlightUsagesHandlerFac final Collection<PsiClassType> psiClassTypes = ExceptionUtil.collectUnhandledExceptions(method.getBody(), method.getBody()); - return new HighlightExceptionsHandler(editor, file, target, psiClassTypes.toArray(new PsiClassType[psiClassTypes.size()]), method.getBody(), Condition.TRUE); + return new HighlightExceptionsHandler(editor, file, target, psiClassTypes.toArray(new PsiClassType[psiClassTypes.size()]), method.getBody(), Conditions.<PsiType>alwaysTrue()); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddAnnotationIntention.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddAnnotationIntention.java index 899da3035ce5..027928a4f695 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddAnnotationIntention.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddAnnotationIntention.java @@ -56,9 +56,11 @@ public abstract class AddAnnotationIntention extends BaseIntentionAction { Pair<String, String[]> annotations = getAnnotations(project); String toAdd = annotations.first; String[] toRemove = annotations.second; - if (toRemove.length > 0 && AnnotationUtil.isAnnotated(owner, toRemove[0], false, false)) return false; + if (toRemove.length > 0 && isAnnotatedSkipInferred(owner, toRemove)) { + return false; + } setText(AddAnnotationPsiFix.calcText(owner, toAdd)); - if (AnnotationUtil.isAnnotated(owner, toAdd, false, false)) return false; + if (isAnnotatedSkipInferred(owner, toAdd)) return false; if (owner instanceof PsiMethod) { PsiType returnType = ((PsiMethod)owner).getReturnType(); @@ -73,6 +75,11 @@ public abstract class AddAnnotationIntention extends BaseIntentionAction { return true; } + private static boolean isAnnotatedSkipInferred(PsiModifierListOwner owner, String... annoFqns) { + PsiAnnotation annotation = AnnotationUtil.findAnnotation(owner, false, annoFqns); + return annotation != null && !AnnotationUtil.isInferredAnnotation(annotation); + } + @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(file, editor.getCaretModel().getOffset()); diff --git a/java/java-impl/src/com/intellij/codeInspection/equalsAndHashcode/EqualsAndHashcode.java b/java/java-impl/src/com/intellij/codeInspection/equalsAndHashcode/EqualsAndHashcode.java new file mode 100644 index 000000000000..3887640051c4 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInspection/equalsAndHashcode/EqualsAndHashcode.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection.equalsAndHashcode; + +import com.intellij.codeInsight.generation.GenerateEqualsHandler; +import com.intellij.codeInspection.InspectionsBundle; +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +/** + * @author Bas Leijdekkers + */ +public class EqualsAndHashcode extends EqualsAndHashcodeBase { + + protected LocalQuickFix[] buildFixes(boolean isOnTheFly, boolean hasEquals) { + if (!isOnTheFly) { + return LocalQuickFix.EMPTY_ARRAY; + } + return new LocalQuickFix[]{new GenerateEqualsHashcodeFix(hasEquals)}; + } + + private static class GenerateEqualsHashcodeFix implements LocalQuickFix { + + private final boolean myHasEquals; + + public GenerateEqualsHashcodeFix(boolean hasEquals) { + myHasEquals = hasEquals; + } + + @NotNull + @Override + public String getName() { + return myHasEquals + ? InspectionsBundle.message("inspection.equals.hashcode.generate.hashcode.quickfix") + : InspectionsBundle.message("inspection.equals.hashcode.generate.equals.quickfix"); + } + + @NotNull + @Override + public String getFamilyName() { + return getName(); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); + if (editor == null) { + return; + } + final PsiElement element = descriptor.getPsiElement(); + new GenerateEqualsHandler().invoke(project, editor, element.getContainingFile()); + } + } +} diff --git a/java/java-impl/src/com/intellij/codeInspection/inferNullity/InferNullityAnnotationsAction.java b/java/java-impl/src/com/intellij/codeInspection/inferNullity/InferNullityAnnotationsAction.java index f9127f0b48a5..df49b83ff48d 100644 --- a/java/java-impl/src/com/intellij/codeInspection/inferNullity/InferNullityAnnotationsAction.java +++ b/java/java-impl/src/com/intellij/codeInspection/inferNullity/InferNullityAnnotationsAction.java @@ -159,7 +159,7 @@ public class InferNullityAnnotationsAction extends BaseAnalysisAction { } else if (Messages.showOkCancelDialog(project, "Infer Nullity Annotations requires that the nullity annotations" + " be available in all your project sources.\n\nYou will need to add annotations.jar as a library. " + - "It is possible to configure custom jar in e.g. Constant Conditions & Exceptions inspection or use JetBrains annotations available in installation. " + + "It is possible to configure custom JAR in e.g. Constant Conditions & Exceptions inspection or use JetBrains annotations available in installation. " + " IntelliJ IDEA nullity annotations are freely usable and redistributable under the Apache 2.0 license. Would you like to do it now?", INFER_NULLITY_ANNOTATIONS, Messages.getErrorIcon()) == Messages.OK) { ApplicationManager.getApplication().invokeLater(new Runnable() { diff --git a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java index 5c226b84500b..4aff727524bf 100644 --- a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java +++ b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java @@ -100,7 +100,7 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ return super.getFindUsagesDialog(isSingleFile, toShowInNewTab, mustOpenInNewTab); } - private static boolean askWhetherShouldSearchForParameterInOverridingMethods(final PsiElement psiElement, final PsiParameter parameter) { + private static boolean askWhetherShouldSearchForParameterInOverridingMethods(@NotNull PsiElement psiElement, @NotNull PsiParameter parameter) { return Messages.showOkCancelDialog(psiElement.getProject(), FindBundle.message("find.parameter.usages.in.overriding.methods.prompt", parameter.getName()), FindBundle.message("find.parameter.usages.in.overriding.methods.title"), @@ -283,10 +283,10 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ final JavaVariableFindUsagesOptions varOptions = (JavaVariableFindUsagesOptions) options; if (varOptions.isReadAccess || varOptions.isWriteAccess){ if (varOptions.isReadAccess && varOptions.isWriteAccess){ - if (!addElementUsages(element, processor, options)) return false; + if (!addElementUsages(element, options, processor)) return false; } else{ - if (!addElementUsages(element, new Processor<UsageInfo>() { + if (!addElementUsages(element, varOptions, new Processor<UsageInfo>() { @Override public boolean process(UsageInfo info) { final PsiElement element = info.getElement(); @@ -296,12 +296,12 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ } return true; } - }, varOptions)) return false; + })) return false; } } } else if (options.isUsages) { - if (!addElementUsages(element, processor, options)) return false; + if (!addElementUsages(element, options, processor)) return false; } boolean success = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() { @@ -325,29 +325,35 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ if (!success) return false; if (options instanceof JavaPackageFindUsagesOptions && ((JavaPackageFindUsagesOptions)options).isClassesUsages){ - if (!addClassesUsages((PsiPackage)element, processor, (JavaPackageFindUsagesOptions)options)) return false; + if (!addClassesUsages((PsiPackage)element, (JavaPackageFindUsagesOptions)options, processor)) return false; } if (options instanceof JavaClassFindUsagesOptions) { final JavaClassFindUsagesOptions classOptions = (JavaClassFindUsagesOptions)options; final PsiClass psiClass = (PsiClass)element; + PsiManager manager = ApplicationManager.getApplication().runReadAction(new Computable<PsiManager>() { + @Override + public PsiManager compute() { + return psiClass.getManager(); + } + }); if (classOptions.isMethodsUsages){ - if (!addMethodsUsages(psiClass, processor, classOptions)) return false; + if (!addMethodsUsages(psiClass, manager, classOptions, processor)) return false; } if (classOptions.isFieldsUsages){ - if (!addFieldsUsages(psiClass, processor, classOptions)) return false; + if (!addFieldsUsages(psiClass, manager, classOptions, processor)) return false; } if (psiClass.isInterface()) { if (classOptions.isDerivedInterfaces){ if (classOptions.isImplementingClasses){ - if (!addInheritors(psiClass, processor, classOptions)) return false; + if (!addInheritors(psiClass, classOptions, processor)) return false; } else{ - if (!addDerivedInterfaces(psiClass, processor, classOptions)) return false; + if (!addDerivedInterfaces(psiClass, classOptions, processor)) return false; } } else if (classOptions.isImplementingClasses){ - if (!addImplementingClasses(psiClass, processor, classOptions)) return false; + if (!addImplementingClasses(psiClass, classOptions, processor)) return false; } if (classOptions.isImplementingClasses) { @@ -355,13 +361,13 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ new PsiElementProcessor<PsiFunctionalExpression>() { @Override public boolean execute(@NotNull PsiFunctionalExpression expression) { - return addResult(processor, expression, options); + return addResult(expression, options, processor); } })); } } else if (classOptions.isDerivedClasses) { - if (!addInheritors(psiClass, processor, classOptions)) return false; + if (!addInheritors(psiClass, classOptions, processor)) return false; } } @@ -380,14 +386,14 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ new PsiElementProcessor<PsiFunctionalExpression>() { @Override public boolean execute(@NotNull PsiFunctionalExpression expression) { - return addResult(processor, expression, options); + return addResult(expression, options, processor); } })); } } if (element instanceof PomTarget) { - if (!addAliasingUsages((PomTarget)element, processor, options)) return false; + if (!addAliasingUsages((PomTarget)element, options, processor)) return false; } final Boolean isSearchable = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() { @Override @@ -403,8 +409,8 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ } private static boolean addAliasingUsages(@NotNull PomTarget pomTarget, - @NotNull final Processor<UsageInfo> processor, - @NotNull final FindUsagesOptions options) { + @NotNull final FindUsagesOptions options, + @NotNull final Processor<UsageInfo> processor) { for (AliasingPsiTargetMapper aliasingPsiTargetMapper : Extensions.getExtensions(AliasingPsiTargetMapper.EP_NAME)) { for (AliasingPsiTarget psiTarget : aliasingPsiTargetMapper.getTargets(pomTarget)) { boolean success = ReferencesSearch @@ -412,7 +418,7 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ .forEach(new ReadActionProcessor<PsiReference>() { @Override public boolean processInReadAction(final PsiReference reference) { - return addResult(processor, reference, options); + return addResult(reference, options, processor); } }); if (!success) return false; @@ -428,15 +434,15 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ new PsiElementProcessor<PsiMethod>() { @Override public boolean execute(@NotNull PsiMethod element) { - return addResult(processor, element.getNavigationElement(), options); + return addResult(element.getNavigationElement(), options, processor); } })); } private static boolean addClassesUsages(@NotNull PsiPackage aPackage, - @NotNull final Processor<UsageInfo> processor, - @NotNull final JavaPackageFindUsagesOptions options) { + @NotNull final JavaPackageFindUsagesOptions options, + @NotNull final Processor<UsageInfo> processor) { ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator(); if (progress != null){ progress.pushState(); @@ -446,18 +452,19 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ addClassesInPackage(aPackage, options.isIncludeSubpackages, classes); for (final PsiClass aClass : classes) { if (progress != null) { - progress.setText(FindBundle.message("find.searching.for.references.to.class.progress", ApplicationManager.getApplication().runReadAction(new Computable<String>(){ + String name = ApplicationManager.getApplication().runReadAction(new Computable<String>() { @Override public String compute() { return aClass.getName(); } - }))); + }); + progress.setText(FindBundle.message("find.searching.for.references.to.class.progress", name)); progress.checkCanceled(); } boolean success = ReferencesSearch.search(new ReferencesSearch.SearchParameters(aClass, options.searchScope, false, options.fastTrack)).forEach(new ReadActionProcessor<PsiReference>() { @Override public boolean processInReadAction(final PsiReference psiReference) { - return addResult(processor, psiReference, options); + return addResult(psiReference, options, processor); } }); if (!success) return false; @@ -469,8 +476,13 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ return true; } - private static void addClassesInPackage(@NotNull PsiPackage aPackage, boolean includeSubpackages, @NotNull List<PsiClass> array) { - PsiDirectory[] dirs = aPackage.getDirectories(); + private static void addClassesInPackage(@NotNull final PsiPackage aPackage, boolean includeSubpackages, @NotNull List<PsiClass> array) { + PsiDirectory[] dirs = ApplicationManager.getApplication().runReadAction(new Computable<PsiDirectory[]>() { + @Override + public PsiDirectory[] compute() { + return aPackage.getDirectories(); + } + }); for (PsiDirectory dir : dirs) { addClassesInDirectory(dir, includeSubpackages, array); } @@ -495,22 +507,40 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ } private static boolean addMethodsUsages(@NotNull final PsiClass aClass, - @NotNull final Processor<UsageInfo> processor, - @NotNull final JavaClassFindUsagesOptions options) { + @NotNull final PsiManager manager, + @NotNull final JavaClassFindUsagesOptions options, + @NotNull final Processor<UsageInfo> processor) { if (options.isIncludeInherited) { - final PsiManager manager = aClass.getManager(); - PsiMethod[] methods = aClass.getAllMethods(); - MethodsLoop: + final PsiMethod[] methods = ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod[]>() { + @Override + public PsiMethod[] compute() { + return aClass.getAllMethods(); + } + }); for(int i = 0; i < methods.length; i++){ final PsiMethod method = methods[i]; - // filter overriden methods - MethodSignature methodSignature = method.getSignature(PsiSubstitutor.EMPTY); - for(int j = 0; j < i; j++){ - if (methodSignature.equals(methods[j].getSignature(PsiSubstitutor.EMPTY))) continue MethodsLoop; - } - final PsiClass methodClass = method.getContainingClass(); - if (methodClass != null && manager.areElementsEquivalent(methodClass, aClass)){ - if (!addElementUsages(methods[i], processor, options)) return false; + // filter overridden methods + final int finalI = i; + final PsiClass methodClass = + ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() { + @Override + public PsiClass compute() { + MethodSignature methodSignature = method.getSignature(PsiSubstitutor.EMPTY); + for (int j = 0; j < finalI; j++) { + if (methodSignature.equals(methods[j].getSignature(PsiSubstitutor.EMPTY))) return null; + } + return method.getContainingClass(); + } + }); + if (methodClass == null) continue; + boolean equivalent = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() { + @Override + public Boolean compute() { + return manager.areElementsEquivalent(methodClass, aClass); + } + }); + if (equivalent){ + if (!addElementUsages(method, options, processor)) return false; } else { MethodReferencesSearch.SearchParameters parameters = @@ -519,7 +549,7 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ .forEach(new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() { @Override public boolean execute(PsiReference reference) { - addResultFromReference(reference, methodClass, manager, aClass, processor, options); + addResultFromReference(reference, methodClass, manager, aClass, options, processor); return true; } })); @@ -528,35 +558,59 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ } } else { - for (PsiMethod method : aClass.getMethods()) { - if (!addElementUsages(method, processor, options)) return false; + PsiMethod[] methods = ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod[]>() { + @Override + public PsiMethod[] compute() { + return aClass.getMethods(); + } + }); + for (PsiMethod method : methods) { + if (!addElementUsages(method, options, processor)) return false; } } return true; } private static boolean addFieldsUsages(@NotNull final PsiClass aClass, - @NotNull final Processor<UsageInfo> processor, - @NotNull final JavaClassFindUsagesOptions options) { + @NotNull final PsiManager manager, + @NotNull final JavaClassFindUsagesOptions options, + @NotNull final Processor<UsageInfo> processor) { if (options.isIncludeInherited) { - final PsiManager manager = aClass.getManager(); - PsiField[] fields = aClass.getAllFields(); - FieldsLoop: + final PsiField[] fields = ApplicationManager.getApplication().runReadAction(new Computable<PsiField[]>() { + @Override + public PsiField[] compute() { + return aClass.getAllFields(); + } + }); for (int i = 0; i < fields.length; i++) { final PsiField field = fields[i]; // filter hidden fields - for (int j = 0; j < i; j++) { - if (Comparing.strEqual(field.getName(), fields[j].getName())) continue FieldsLoop; - } - final PsiClass fieldClass = field.getContainingClass(); - if (manager.areElementsEquivalent(fieldClass, aClass)) { - if (!addElementUsages(fields[i], processor, options)) return false; + final int finalI = i; + final PsiClass fieldClass = + ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() { + @Override + public PsiClass compute() { + for (int j = 0; j < finalI; j++) { + if (Comparing.strEqual(field.getName(), fields[j].getName())) return null; + } + return field.getContainingClass(); + } + }); + if (fieldClass == null) continue; + boolean equivalent = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() { + @Override + public Boolean compute() { + return manager.areElementsEquivalent(fieldClass, aClass); + } + }); + if (equivalent) { + if (!addElementUsages(fields[i], options, processor)) return false; } else { boolean success = ReferencesSearch.search(new ReferencesSearch.SearchParameters(field, options.searchScope, false, options.fastTrack)).forEach(new ReadActionProcessor<PsiReference>() { @Override public boolean processInReadAction(final PsiReference reference) { - return addResultFromReference(reference, fieldClass, manager, aClass, processor, options); + return addResultFromReference(reference, fieldClass, manager, aClass, options, processor); } }); if (!success) return false; @@ -571,14 +625,14 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ } }); for (PsiField field : fields) { - if (!addElementUsages(field, processor, options)) return false; + if (!addElementUsages(field, options, processor)) return false; } } return true; } @Nullable - private static PsiClass getFieldOrMethodAccessedClass(@NotNull PsiReferenceExpression ref, PsiClass fieldOrMethodClass) { + private static PsiClass getFieldOrMethodAccessedClass(@NotNull PsiReferenceExpression ref, @NotNull PsiClass fieldOrMethodClass) { PsiElement[] children = ref.getChildren(); if (children.length > 1 && children[0] instanceof PsiExpression) { PsiExpression expr = (PsiExpression)children[0]; @@ -606,39 +660,39 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ } private static boolean addInheritors(@NotNull PsiClass aClass, - @NotNull final Processor<UsageInfo> processor, - @NotNull final JavaClassFindUsagesOptions options) { + @NotNull final JavaClassFindUsagesOptions options, + @NotNull final Processor<UsageInfo> processor) { return ClassInheritorsSearch.search(aClass, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>( new PsiElementProcessor<PsiClass>() { @Override public boolean execute(@NotNull PsiClass element) { - return addResult(processor, element, options); + return addResult(element, options, processor); } })); } private static boolean addDerivedInterfaces(@NotNull PsiClass anInterface, - @NotNull final Processor<UsageInfo> processor, - @NotNull final JavaClassFindUsagesOptions options) { + @NotNull final JavaClassFindUsagesOptions options, + @NotNull final Processor<UsageInfo> processor) { return ClassInheritorsSearch.search(anInterface, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>( new PsiElementProcessor<PsiClass>() { @Override public boolean execute(@NotNull PsiClass inheritor) { - return !inheritor.isInterface() || addResult(processor, inheritor, options); + return !inheritor.isInterface() || addResult(inheritor, options, processor); } })); } private static boolean addImplementingClasses(@NotNull PsiClass anInterface, - @NotNull final Processor<UsageInfo> processor, - @NotNull final JavaClassFindUsagesOptions options) { + @NotNull final JavaClassFindUsagesOptions options, + @NotNull final Processor<UsageInfo> processor) { return ClassInheritorsSearch.search(anInterface, options.searchScope, options.isCheckDeepInheritance).forEach(new PsiElementProcessorAdapter<PsiClass>( new PsiElementProcessor<PsiClass>() { @Override public boolean execute(@NotNull PsiClass inheritor) { - return inheritor.isInterface() || addResult(processor, inheritor, options); + return inheritor.isInterface() || addResult(inheritor, options, processor); } })); } @@ -647,14 +701,14 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ @NotNull PsiClass methodClass, @NotNull PsiManager manager, @NotNull PsiClass aClass, - @NotNull Processor<UsageInfo> processor, - @NotNull FindUsagesOptions options) { + @NotNull FindUsagesOptions options, + @NotNull Processor<UsageInfo> processor) { PsiElement refElement = reference.getElement(); if (refElement instanceof PsiReferenceExpression) { PsiClass usedClass = getFieldOrMethodAccessedClass((PsiReferenceExpression)refElement, methodClass); if (usedClass != null) { if (manager.areElementsEquivalent(usedClass, aClass) || usedClass.isInheritor(aClass, true)) { - if (!addResult(processor, refElement, options)) return false; + if (!addResult(refElement, options, processor)) return false; } } } @@ -662,8 +716,8 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ } private static boolean addElementUsages(@NotNull final PsiElement element, - @NotNull final Processor<UsageInfo> processor, - @NotNull final FindUsagesOptions options) { + @NotNull final FindUsagesOptions options, + @NotNull final Processor<UsageInfo> processor) { final SearchScope searchScope = options.searchScope; final PsiClass[] parentClass = new PsiClass[1]; if (element instanceof PsiMethod && ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() { @@ -684,7 +738,7 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ .forEach(new ReadActionProcessor<PsiReference>() { @Override public boolean processInReadAction(final PsiReference ref) { - return addResult(processor, ref, options); + return addResult(ref, options, processor); } }); } @@ -694,7 +748,7 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ final ReadActionProcessor<PsiReference> consumer = new ReadActionProcessor<PsiReference>() { @Override public boolean processInReadAction(final PsiReference ref) { - return addResult(processor, ref, options); + return addResult(ref, options, processor); } }; @@ -708,11 +762,13 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ return ReferencesSearch.search(new ReferencesSearch.SearchParameters(element, searchScope, false, options.fastTrack)).forEach(consumer); } - private static boolean addResult(@NotNull Processor<UsageInfo> processor, @NotNull PsiElement element, @NotNull FindUsagesOptions options) { + private static boolean addResult(@NotNull PsiElement element, + @NotNull FindUsagesOptions options, + @NotNull Processor<UsageInfo> processor) { return !filterUsage(element, options) || processor.process(new UsageInfo(element)); } - private static boolean addResult(Processor<UsageInfo> processor, PsiReference ref, FindUsagesOptions options) { + private static boolean addResult(@NotNull PsiReference ref, @NotNull FindUsagesOptions options, @NotNull Processor<UsageInfo> processor) { if (filterUsage(ref.getElement(), options)){ TextRange rangeInElement = ref.getRangeInElement(); return processor.process(new UsageInfo(ref.getElement(), rangeInElement.getStartOffset(), rangeInElement.getEndOffset(), false)); @@ -720,7 +776,7 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ return true; } - private static boolean filterUsage(PsiElement usage, FindUsagesOptions options) { + private static boolean filterUsage(PsiElement usage, @NotNull FindUsagesOptions options) { if (!(usage instanceof PsiJavaCodeReferenceElement)) { return true; } @@ -780,5 +836,4 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ } return super.findReferencesToHighlight(target, searchScope); } - } diff --git a/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java b/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java index 2f684304ae58..c6c4f6c144d2 100644 --- a/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java +++ b/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java @@ -19,6 +19,7 @@ import com.intellij.application.options.IndentOptionsEditor; import com.intellij.application.options.JavaIndentOptionsEditor; import com.intellij.lang.Language; import com.intellij.lang.java.JavaLanguage; +import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.pom.java.LanguageLevel; @@ -57,8 +58,8 @@ public class JavaLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett @Override public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer, @NotNull SettingsType settingsType) { - consumer.showAllStandardOptions(); if (settingsType == SettingsType.SPACING_SETTINGS) { + consumer.showAllStandardOptions(); consumer.showCustomOption(JavaCodeStyleSettings.class, "SPACES_WITHIN_ANGLE_BRACKETS", "Angle brackets",CodeStyleSettingsCustomizable.SPACES_WITHIN); String groupName = CodeStyleSettingsCustomizable.SPACES_IN_TYPE_ARGUMENTS; @@ -69,6 +70,95 @@ public class JavaLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett consumer.showCustomOption(JavaCodeStyleSettings.class, "SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER", "Before opening angle bracket", groupName); consumer.showCustomOption(JavaCodeStyleSettings.class, "SPACE_AROUND_TYPE_BOUNDS_IN_TYPE_PARAMETERS", "Around type bounds", groupName); } + else if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) { + consumer.showStandardOptions("RIGHT_MARGIN", + "KEEP_CONTROL_STATEMENT_IN_ONE_LINE", + "LINE_COMMENT_AT_FIRST_COLUMN", + "BLOCK_COMMENT_AT_FIRST_COLUMN", + "KEEP_LINE_BREAKS", + "KEEP_FIRST_COLUMN_COMMENT", + "CALL_PARAMETERS_WRAP", + "PREFER_PARAMETERS_WRAP", + "CALL_PARAMETERS_LPAREN_ON_NEXT_LINE", + "CALL_PARAMETERS_RPAREN_ON_NEXT_LINE", + "METHOD_PARAMETERS_WRAP", + "METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE", + "METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE", + "RESOURCE_LIST_WRAP", + "RESOURCE_LIST_LPAREN_ON_NEXT_LINE", + "RESOURCE_LIST_RPAREN_ON_NEXT_LINE", + "EXTENDS_LIST_WRAP", + "THROWS_LIST_WRAP", + "EXTENDS_KEYWORD_WRAP", + "THROWS_KEYWORD_WRAP", + "METHOD_CALL_CHAIN_WRAP", + "PARENTHESES_EXPRESSION_LPAREN_WRAP", + "PARENTHESES_EXPRESSION_RPAREN_WRAP", + "BINARY_OPERATION_WRAP", + "BINARY_OPERATION_SIGN_ON_NEXT_LINE", + "TERNARY_OPERATION_WRAP", + "TERNARY_OPERATION_SIGNS_ON_NEXT_LINE", + "MODIFIER_LIST_WRAP", + "KEEP_SIMPLE_BLOCKS_IN_ONE_LINE", + "KEEP_SIMPLE_METHODS_IN_ONE_LINE", + "KEEP_SIMPLE_CLASSES_IN_ONE_LINE", + "KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE", + "FOR_STATEMENT_WRAP", + "FOR_STATEMENT_LPAREN_ON_NEXT_LINE", + "FOR_STATEMENT_RPAREN_ON_NEXT_LINE", + "ARRAY_INITIALIZER_WRAP", + "ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE", + "ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE", + "ASSIGNMENT_WRAP", + "PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE", + "LABELED_STATEMENT_WRAP", + "ASSERT_STATEMENT_WRAP", + "ASSERT_STATEMENT_COLON_ON_NEXT_LINE", + "IF_BRACE_FORCE", + "DOWHILE_BRACE_FORCE", + "WHILE_BRACE_FORCE", + "FOR_BRACE_FORCE", + "WRAP_LONG_LINES", + "METHOD_ANNOTATION_WRAP", + "CLASS_ANNOTATION_WRAP", + "FIELD_ANNOTATION_WRAP", + "PARAMETER_ANNOTATION_WRAP", + "VARIABLE_ANNOTATION_WRAP", + "ALIGN_MULTILINE_CHAINED_METHODS", + "ALIGN_MULTILINE_PARAMETERS", + "ALIGN_MULTILINE_PARAMETERS_IN_CALLS", + "ALIGN_MULTILINE_RESOURCES", + "ALIGN_MULTILINE_FOR", + "INDENT_WHEN_CASES", + "ALIGN_MULTILINE_BINARY_OPERATION", + "ALIGN_MULTILINE_ASSIGNMENT", + "ALIGN_MULTILINE_TERNARY_OPERATION", + "ALIGN_MULTILINE_THROWS_LIST", + "ALIGN_THROWS_KEYWORD", + "ALIGN_MULTILINE_EXTENDS_LIST", + "ALIGN_MULTILINE_METHOD_BRACKETS", + "ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION", + "ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION", + "ALIGN_GROUP_FIELD_DECLARATIONS", + "BRACE_STYLE", + "CLASS_BRACE_STYLE", + "METHOD_BRACE_STYLE", + "USE_FLYING_GEESE_BRACES", + "FLYING_GEESE_BRACES_GAP", + "DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS", + "ELSE_ON_NEW_LINE", + "WHILE_ON_NEW_LINE", + "CATCH_ON_NEW_LINE", + "FINALLY_ON_NEW_LINE", + "INDENT_CASE_FROM_SWITCH", + "SPECIAL_ELSE_IF_TREATMENT", + "ENUM_CONSTANTS_WRAP"); + String groupName = ApplicationBundle.message("wrapping.fields.annotation"); + consumer.showCustomOption(JavaCodeStyleSettings.class, "DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION", "Do not wrap after single annotation", groupName); + } + else { + consumer.showAllStandardOptions(); + } } @Override diff --git a/java/java-impl/src/com/intellij/ide/actions/CreatePackageInfoAction.java b/java/java-impl/src/com/intellij/ide/actions/CreatePackageInfoAction.java index 64a8c1bcfcb5..8fd9f0d422db 100644 --- a/java/java-impl/src/com/intellij/ide/actions/CreatePackageInfoAction.java +++ b/java/java-impl/src/com/intellij/ide/actions/CreatePackageInfoAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -41,7 +41,7 @@ import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; */ public class CreatePackageInfoAction extends CreateFromTemplateActionBase implements DumbAware { - protected CreatePackageInfoAction() { + public CreatePackageInfoAction() { super(IdeBundle.message("action.create.new.package-info.title"), IdeBundle.message("action.create.new.package-info.description"), AllIcons.FileTypes.Java); } diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java b/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java index 7e0515726610..ef745b3aaa8b 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java @@ -62,8 +62,9 @@ public class ClassesTreeStructureProvider implements SelectableTreeStructureProv if (originalElement instanceof PsiFile) { PsiFile classFile = (PsiFile)originalElement; final VirtualFile virtualClassFile = classFile.getVirtualFile(); - if (virtualClassFile != null && fileIndex.isInLibraryClasses(virtualClassFile) && - classOwner.getManager().areElementsEquivalent(classOwner.getContainingDirectory(), classFile.getContainingDirectory())) { + if (virtualClassFile != null && fileIndex.isInLibraryClasses(virtualClassFile) + && !classOwner.getManager().areElementsEquivalent(classOwner, classFile) + && classOwner.getManager().areElementsEquivalent(classOwner.getContainingDirectory(), classFile.getContainingDirectory())) { continue; } } diff --git a/java/java-impl/src/com/intellij/ide/util/scopeChooser/ClassHierarchyScopeDescriptor.java b/java/java-impl/src/com/intellij/ide/util/scopeChooser/ClassHierarchyScopeDescriptor.java index 356933823226..05b2578e5df1 100644 --- a/java/java-impl/src/com/intellij/ide/util/scopeChooser/ClassHierarchyScopeDescriptor.java +++ b/java/java-impl/src/com/intellij/ide/util/scopeChooser/ClassHierarchyScopeDescriptor.java @@ -69,23 +69,25 @@ public class ClassHierarchyScopeDescriptor extends ScopeDescriptor { chooser.showDialog(); PsiClass aClass = chooser.getSelected(); - if (aClass == null) return null; + if (aClass == null) { + myCachedScope = GlobalSearchScope.EMPTY_SCOPE; + } else { + final List<PsiElement> classesToSearch = new LinkedList<PsiElement>(); + classesToSearch.add(aClass); - final List<PsiElement> classesToSearch = new LinkedList<PsiElement>(); - classesToSearch.add(aClass); + classesToSearch.addAll(ClassInheritorsSearch.search(aClass, true).findAll()); - classesToSearch.addAll(ClassInheritorsSearch.search(aClass, true).findAll()); + FunctionalExpressionSearch.search(aClass).forEach(new Processor<PsiFunctionalExpression>() { + @Override + public boolean process(PsiFunctionalExpression expression) { + classesToSearch.add(expression); + return true; + } + }); - FunctionalExpressionSearch.search(aClass).forEach(new Processor<PsiFunctionalExpression>() { - @Override - public boolean process(PsiFunctionalExpression expression) { - classesToSearch.add(expression); - return true; - } - }); - - myCachedScope = new LocalSearchScope(PsiUtilCore.toPsiElementArray(classesToSearch), - IdeBundle.message("scope.hierarchy", ClassPresentationUtil.getNameForClass(aClass, true))); + myCachedScope = new LocalSearchScope(PsiUtilCore.toPsiElementArray(classesToSearch), + IdeBundle.message("scope.hierarchy", ClassPresentationUtil.getNameForClass(aClass, true))); + } } return myCachedScope; diff --git a/java/java-impl/src/com/intellij/jarFinder/FindJarFix.java b/java/java-impl/src/com/intellij/jarFinder/FindJarFix.java index ee203e34deac..e82f79652074 100644 --- a/java/java-impl/src/com/intellij/jarFinder/FindJarFix.java +++ b/java/java-impl/src/com/intellij/jarFinder/FindJarFix.java @@ -69,7 +69,7 @@ public abstract class FindJarFix<T extends PsiElement> implements IntentionActio @NotNull @Override public String getText() { - return "Find jar on web"; + return "Find JAR on web"; } @NotNull @@ -190,7 +190,7 @@ public abstract class FindJarFix<T extends PsiElement> implements IntentionActio } else { JBPopupFactory.getInstance() .createListPopupBuilder(libNames) - .setTitle("Select a jar file") + .setTitle("Select a JAR file") .setItemChoosenCallback(new Runnable() { @Override public void run() { diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaAwareProjectJdkTableImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaAwareProjectJdkTableImpl.java index 44f0132acbb5..fd9fa64eae66 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaAwareProjectJdkTableImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaAwareProjectJdkTableImpl.java @@ -22,17 +22,16 @@ package com.intellij.openapi.projectRoots.impl; import com.intellij.openapi.components.*; import com.intellij.openapi.project.ProjectBundle; -import com.intellij.openapi.projectRoots.*; +import com.intellij.openapi.projectRoots.JavaSdk; +import com.intellij.openapi.projectRoots.ProjectJdkTable; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.SdkTypeId; import com.intellij.util.SystemProperties; import org.jdom.Element; @State( - name="ProjectJdkTable", - roamingType = RoamingType.DISABLED, - storages= { - @Storage( - file = StoragePathMacros.APP_CONFIG + "/jdk.table.xml" - )} + name = "ProjectJdkTable", + storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/jdk.table.xml", roamingType = RoamingType.DISABLED)} ) public class JavaAwareProjectJdkTableImpl extends ProjectJdkTableImpl { public static JavaAwareProjectJdkTableImpl getInstanceEx() { diff --git a/java/java-impl/src/com/intellij/openapi/roots/impl/LanguageLevelProjectExtensionImpl.java b/java/java-impl/src/com/intellij/openapi/roots/impl/LanguageLevelProjectExtensionImpl.java index 496795b85444..836d6e005113 100644 --- a/java/java-impl/src/com/intellij/openapi/roots/impl/LanguageLevelProjectExtensionImpl.java +++ b/java/java-impl/src/com/intellij/openapi/roots/impl/LanguageLevelProjectExtensionImpl.java @@ -97,7 +97,9 @@ public class LanguageLevelProjectExtensionImpl extends LanguageLevelProjectExten @Override public void languageLevelsChanged() { - JavaLanguageLevelPusher.pushLanguageLevel(myProject); + if (!myProject.isDefault()) { + JavaLanguageLevelPusher.pushLanguageLevel(myProject); + } } @Override diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java b/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java index 7e117e3ed0c7..b7d0f71fe00d 100644 --- a/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java +++ b/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java @@ -30,4 +30,5 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings { public boolean SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER = false; public boolean SPACE_AROUND_TYPE_BOUNDS_IN_TYPE_PARAMETERS = true; + public boolean DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION = false; } diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java index 4d225e65d88b..5230805aa03c 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java @@ -1129,7 +1129,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { @Override public void visitModifierList(PsiModifierList list) { - createSpaceInCode(true); + myResult = Spacing.createSpacing(1, 1, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); } @Override diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java index 954f03248b9c..5b05ced2d5a1 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java @@ -20,6 +20,7 @@ import com.intellij.formatting.WrapType; import com.intellij.lang.ASTNode; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.psi.codeStyle.JavaCodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.formatter.java.JavaFormatterUtil; import com.intellij.psi.formatter.java.wrap.JavaWrapManager; @@ -29,6 +30,7 @@ import com.intellij.psi.impl.source.tree.CompositeElement; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.tree.IElementType; import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static com.intellij.psi.formatter.java.JavaFormatterUtil.getWrapType; @@ -69,6 +71,7 @@ public class JavaChildWrapArranger { CommonCodeStyleSettings settings, Wrap suggestedWrap, ReservedWrapsProvider reservedWrapsProvider) { + final JavaCodeStyleSettings javaSettings = settings.getRootSettings().getCustomSettings(JavaCodeStyleSettings.class); ASTNode directParent = child.getTreeParent(); int role = ((CompositeElement)directParent).getChildRole(child); @@ -153,7 +156,7 @@ public class JavaChildWrapArranger { if (prev != null && prev.getElementType() == JavaElementType.MODIFIER_LIST) { ASTNode last = prev.getLastChildNode(); if (last != null && last.getElementType() == JavaElementType.ANNOTATION) { - if (isTypeAnnotation(last.getPsi())) { + if (isTypeAnnotation(last.getPsi()) || javaSettings.DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION && isFieldModifierListWithSingleAnnotation(prev)) { return Wrap.createWrap(WrapType.NONE, false); } else { @@ -182,6 +185,10 @@ public class JavaChildWrapArranger { ASTNode prev = FormatterUtil.getPreviousNonWhitespaceSibling(child); if (prev != null && prev.getElementType() == JavaElementType.ANNOTATION) { + if (javaSettings.DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION && isFieldModifierListWithSingleAnnotation(parent)) { + return Wrap.createWrap(WrapType.NONE, false); + } + return Wrap.createWrap(getWrapType(getAnnotationWrapType(parent.getTreeParent(), child, settings)), true); } @@ -256,6 +263,23 @@ public class JavaChildWrapArranger { return suggestedWrap; } + private static boolean isFieldModifierListWithSingleAnnotation(@NotNull ASTNode elem) { + ASTNode parent = elem.getTreeParent(); + if (parent != null && parent.getElementType() == JavaElementType.FIELD) { + return isModifierListWithSingleAnnotation(elem); + } + return false; + } + + private static boolean isModifierListWithSingleAnnotation(@NotNull ASTNode elem) { + if (elem.getPsi() instanceof PsiModifierList) { + if (((PsiModifierList)elem.getPsi()).getAnnotations().length == 1) { + return true; + } + } + return false; + } + private static int getAnnotationWrapType(ASTNode parent, ASTNode child, CommonCodeStyleSettings settings) { IElementType nodeType = parent.getElementType(); diff --git a/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelperImpl.java b/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelperImpl.java index 658ee6561e68..0c49938053f0 100644 --- a/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelperImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelperImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -24,11 +24,11 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.module.ModuleUtil; -import com.intellij.openapi.roots.impl.ModifiableModelCommitter; +import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; -import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.roots.impl.ModifiableModelCommitter; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowId; @@ -37,6 +37,9 @@ import com.intellij.psi.*; import com.intellij.psi.impl.PackagePrefixElementFinder; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiModificationTracker; +import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.PsiUtilCore; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; import java.util.ArrayList; @@ -46,22 +49,25 @@ import java.util.List; * @author yole */ public class PsiPackageImplementationHelperImpl extends PsiPackageImplementationHelper { + @NotNull @Override - public GlobalSearchScope adjustAllScope(PsiPackage psiPackage, GlobalSearchScope globalSearchScope) { + public GlobalSearchScope adjustAllScope(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope globalSearchScope) { return NonClasspathClassFinder.addNonClasspathScope(psiPackage.getProject(), globalSearchScope); } + @NotNull @Override - public VirtualFile[] occursInPackagePrefixes(PsiPackage psiPackage) { + public VirtualFile[] occursInPackagePrefixes(@NotNull PsiPackage psiPackage) { List<VirtualFile> result = new ArrayList<VirtualFile>(); final Module[] modules = ModuleManager.getInstance(psiPackage.getProject()).getModules(); + String qualifiedName = psiPackage.getQualifiedName(); for (final Module module : modules) { for (final ContentEntry contentEntry : ModuleRootManager.getInstance(module).getContentEntries()) { final List<SourceFolder> sourceFolders = contentEntry.getSourceFolders(JavaModuleSourceRootTypes.SOURCES); for (final SourceFolder sourceFolder : sourceFolders) { final String packagePrefix = sourceFolder.getPackagePrefix(); - if (packagePrefix.startsWith(psiPackage.getQualifiedName())) { + if (packagePrefix.startsWith(qualifiedName)) { final VirtualFile file = sourceFolder.getFile(); if (file != null) { result.add(file); @@ -71,11 +77,11 @@ public class PsiPackageImplementationHelperImpl extends PsiPackageImplementation } } - return VfsUtil.toVirtualFileArray(result); + return VfsUtilCore.toVirtualFileArray(result); } @Override - public void handleQualifiedNameChange(final PsiPackage psiPackage, final String newQualifiedName) { + public void handleQualifiedNameChange(@NotNull final PsiPackage psiPackage, @NotNull final String newQualifiedName) { ApplicationManager.getApplication().assertWriteAccessAllowed(); final String oldQualifedName = psiPackage.getQualifiedName(); final boolean anyChanged = changePackagePrefixes(psiPackage, oldQualifedName, newQualifiedName); @@ -94,7 +100,7 @@ public class PsiPackageImplementationHelperImpl extends PsiPackageImplementation } } - private static boolean changePackagePrefixes(PsiPackage psiPackage, final String oldQualifiedName, final String newQualifiedName) { + private static boolean changePackagePrefixes(@NotNull PsiPackage psiPackage, @NotNull String oldQualifiedName, @NotNull String newQualifiedName) { final Module[] modules = ModuleManager.getInstance(psiPackage.getProject()).getModules(); List<ModifiableRootModel> modelsToCommit = new ArrayList<ModifiableRootModel>(); for (final Module module : modules) { @@ -128,7 +134,7 @@ public class PsiPackageImplementationHelperImpl extends PsiPackageImplementation } @Override - public void navigate(final PsiPackage psiPackage, final boolean requestFocus) { + public void navigate(@NotNull final PsiPackage psiPackage, final boolean requestFocus) { final Project project = psiPackage.getProject(); ToolWindow window = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.PROJECT_VIEW); window.activate(null); @@ -143,7 +149,8 @@ public class PsiPackageImplementationHelperImpl extends PsiPackageImplementation }); } - private static PsiDirectory[] suggestMostAppropriateDirectories(PsiPackage psiPackage) { + @NotNull + private static PsiDirectory[] suggestMostAppropriateDirectories(@NotNull PsiPackage psiPackage) { final Project project = psiPackage.getProject(); PsiDirectory[] directories = null; final Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); @@ -151,10 +158,20 @@ public class PsiPackageImplementationHelperImpl extends PsiPackageImplementation final Document document = editor.getDocument(); final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); if (psiFile != null) { - final Module module = ModuleUtil.findModuleForPsiElement(psiFile); + final Module module = ModuleUtilCore.findModuleForPsiElement(psiFile); if (module != null) { - directories = psiPackage.getDirectories(GlobalSearchScope.moduleWithDependenciesScope(module)); - } else { + final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(psiFile); + final boolean isInTests = + virtualFile != null && ModuleRootManager.getInstance(module).getFileIndex().isInTestSourceContent(virtualFile); + if (isInTests) { + directories = psiPackage.getDirectories(GlobalSearchScope.moduleTestsWithDependentsScope(module)); + } + + if (directories == null || directories.length == 0) { + directories = psiPackage.getDirectories(GlobalSearchScope.moduleWithDependenciesScope(module)); + } + } + else { directories = psiPackage.getDirectories(GlobalSearchScope.notScope(GlobalSearchScope.projectScope(project))); } } @@ -167,12 +184,13 @@ public class PsiPackageImplementationHelperImpl extends PsiPackageImplementation } @Override - public boolean packagePrefixExists(PsiPackage psiPackage) { + public boolean packagePrefixExists(@NotNull PsiPackage psiPackage) { return PackagePrefixElementFinder.getInstance(psiPackage.getProject()).packagePrefixExists(psiPackage.getQualifiedName()); } + @NotNull @Override - public Object[] getDirectoryCachedValueDependencies(PsiPackage psiPackage) { + public Object[] getDirectoryCachedValueDependencies(@NotNull PsiPackage psiPackage) { return new Object[] { PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, ProjectRootManager.getInstance(psiPackage.getProject()) }; } } diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/AbstractExtractDialog.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/AbstractExtractDialog.java index 7e49181472b0..9f83b6ed080b 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/AbstractExtractDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/AbstractExtractDialog.java @@ -20,25 +20,18 @@ */ package com.intellij.refactoring.extractMethod; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.PsiModifier; import com.intellij.refactoring.util.VariableData; -public abstract class AbstractExtractDialog extends DialogWrapper { - protected AbstractExtractDialog(Project project) { - super(project, true); - } - - - public abstract String getChosenMethodName(); - - public abstract VariableData[] getChosenParameters(); +public interface AbstractExtractDialog { + String getChosenMethodName(); + VariableData[] getChosenParameters(); @PsiModifier.ModifierConstant - public abstract String getVisibility(); - - public abstract boolean isMakeStatic(); + String getVisibility(); + boolean isMakeStatic(); + boolean isChainedConstructor(); - public abstract boolean isChainedConstructor(); + void show(); + boolean isOK(); }
\ No newline at end of file diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java index f4cfccb496ad..fc933de2b80e 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java @@ -21,6 +21,7 @@ import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.ui.VerticalFlowLayout; import com.intellij.openapi.util.text.StringUtil; @@ -59,7 +60,7 @@ import java.awt.event.*; * @author Konstantin Bulenkov */ @SuppressWarnings("MethodMayBeStatic") -public class ExtractMethodDialog extends AbstractExtractDialog { +public class ExtractMethodDialog extends DialogWrapper implements AbstractExtractDialog { public static final String EXTRACT_METHOD_DEFAULT_VISIBILITY = "extract.method.default.visibility"; private final Project myProject; private final PsiType myReturnType; @@ -96,7 +97,7 @@ public class ExtractMethodDialog extends AbstractExtractDialog { String title, String helpId, final PsiElement[] elementsToExtract) { - super(project); + super(project, true); myProject = project; myTargetClass = targetClass; myReturnType = returnType; 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 c61c29c58ff9..0b760502384a 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java @@ -463,14 +463,14 @@ public class ExtractMethodProcessor implements MatchProvider { protected void apply(final AbstractExtractDialog dialog) { myMethodName = dialog.getChosenMethodName(); myVariableDatum = dialog.getChosenParameters(); - myStatic |= dialog.isMakeStatic(); + myStatic = isStatic() | dialog.isMakeStatic(); myIsChainedConstructor = dialog.isChainedConstructor(); myMethodVisibility = dialog.getVisibility(); } protected AbstractExtractDialog createExtractMethodDialog(final boolean direct) { - return new ExtractMethodDialog(myProject, myTargetClass, myInputVariables, myReturnType, myTypeParameterList, - myThrownExceptions, myStatic, myCanBeStatic, myCanBeChainedConstructor, + return new ExtractMethodDialog(myProject, myTargetClass, myInputVariables, myReturnType, getTypeParameterList(), + getThrownExceptions(), isStatic(), isCanBeStatic(), myCanBeChainedConstructor, suggestInitialMethodName(), myRefactoringName, myHelpId, myElements) { protected boolean areTypesDirected() { @@ -575,10 +575,16 @@ public class ExtractMethodProcessor implements MatchProvider { chooseAnchor(); - int col = myEditor.getCaretModel().getLogicalPosition().column; - int line = myEditor.getCaretModel().getLogicalPosition().line; - LogicalPosition pos = new LogicalPosition(0, 0); - myEditor.getCaretModel().moveToLogicalPosition(pos); + LogicalPosition pos1; + if (myEditor != null) { + int col = myEditor.getCaretModel().getLogicalPosition().column; + int line = myEditor.getCaretModel().getLogicalPosition().line; + pos1 = new LogicalPosition(line, col); + LogicalPosition pos = new LogicalPosition(0, 0); + myEditor.getCaretModel().moveToLogicalPosition(pos); + } else { + pos1 = null; + } final SearchScope processConflictsScope = myMethodVisibility.equals(PsiModifier.PRIVATE) ? new LocalSearchScope(myTargetClass) : @@ -610,17 +616,18 @@ public class ExtractMethodProcessor implements MatchProvider { ApplicationManager.getApplication().runWriteAction(extract); } - LogicalPosition pos1 = new LogicalPosition(line, col); - myEditor.getCaretModel().moveToLogicalPosition(pos1); - int offset = myMethodCall.getMethodExpression().getTextRange().getStartOffset(); - myEditor.getCaretModel().moveToOffset(offset); - myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); - myEditor.getSelectionModel().removeSelection(); + if (myEditor != null) { + myEditor.getCaretModel().moveToLogicalPosition(pos1); + int offset = myMethodCall.getMethodExpression().getTextRange().getStartOffset(); + myEditor.getCaretModel().moveToOffset(offset); + myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + myEditor.getSelectionModel().removeSelection(); + } } - private void doExtract() throws IncorrectOperationException { + public void doExtract() throws IncorrectOperationException { - PsiMethod newMethod = generateEmptyMethod(myThrownExceptions, myStatic); + PsiMethod newMethod = generateEmptyMethod(getThrownExceptions(), isStatic()); myExpression = myInputVariables.replaceWrappedReferences(myElements, myExpression); renameInputVariables(); @@ -991,6 +998,10 @@ public class ExtractMethodProcessor implements MatchProvider { return myTargetClass; } + public PsiType getReturnType() { + return myReturnType; + } + private PsiMethod generateEmptyMethod(PsiClassType[] exceptions, boolean isStatic) throws IncorrectOperationException { PsiMethod newMethod; if (myIsChainedConstructor) { @@ -1001,8 +1012,8 @@ public class ExtractMethodProcessor implements MatchProvider { PsiUtil.setModifierProperty(newMethod, PsiModifier.STATIC, isStatic); } PsiUtil.setModifierProperty(newMethod, myMethodVisibility, true); - if (myTypeParameterList != null) { - newMethod.getTypeParameterList().replace(myTypeParameterList); + if (getTypeParameterList() != null) { + newMethod.getTypeParameterList().replace(getTypeParameterList()); } PsiCodeBlock body = newMethod.getBody(); LOG.assertTrue(body != null); @@ -1400,4 +1411,28 @@ public class ExtractMethodProcessor implements MatchProvider { public InputVariables getInputVariables() { return myInputVariables; } + + public PsiTypeParameterList getTypeParameterList() { + return myTypeParameterList; + } + + public PsiClassType[] getThrownExceptions() { + return myThrownExceptions; + } + + public boolean isStatic() { + return myStatic; + } + + public boolean isCanBeStatic() { + return myCanBeStatic; + } + + public PsiElement[] getElements() { + return myElements; + } + + public PsiVariable[] getOutputVariables() { + return myOutputVariables; + } } diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java new file mode 100644 index 000000000000..bb465b9848bb --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java @@ -0,0 +1,254 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.extractMethodObject; + +import com.intellij.codeInsight.CodeInsightUtil; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.controlFlow.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.extractMethod.AbstractExtractDialog; +import com.intellij.refactoring.extractMethod.InputVariables; +import com.intellij.refactoring.extractMethod.PrepareFailedException; +import com.intellij.refactoring.util.RefactoringUtil; +import com.intellij.refactoring.util.VariableData; +import com.intellij.usageView.UsageInfo; +import com.intellij.util.Function; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.VisibilityUtil; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class ExtractLightMethodObjectHandler { + private static final Logger LOG = Logger.getInstance("#" + ExtractLightMethodObjectHandler.class.getName()); + + public static class ExtractedData { + private String myGeneratedCallText; + private PsiClass myGeneratedInnerClass; + private final PsiElement myAnchor; + + public ExtractedData(String generatedCallText, PsiClass generatedInnerClass, PsiElement anchor) { + myGeneratedCallText = generatedCallText; + myGeneratedInnerClass = generatedInnerClass; + myAnchor = anchor; + } + + public PsiElement getAnchor() { + return myAnchor; + } + + public String getGeneratedCallText() { + return myGeneratedCallText; + } + + public PsiClass getGeneratedInnerClass() { + return myGeneratedInnerClass; + } + } + + @Nullable + public static ExtractedData extractLightMethodObject(final Project project, + final PsiFile file, + @NotNull final PsiCodeFragment fragment, + final String methodName) throws PrepareFailedException { + PsiExpression expression = CodeInsightUtil.findExpressionInRange(fragment, 0, fragment.getTextLength()); + final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); + final PsiElement[] elements; + if (expression != null) { + elements = new PsiElement[] {elementFactory.createStatementFromText(expression.getText() + ";", expression)}; + } else { + elements = CodeInsightUtil.findStatementsInRange(fragment, 0, fragment.getTextLength()); + } + if (elements.length == 0) { + return null; + } + + final PsiFile copy = PsiFileFactory.getInstance(project) + .createFileFromText(file.getName(), file.getFileType(), file.getText(), file.getModificationStamp(), false); + + final PsiElement originalContext = fragment.getContext(); + if (originalContext == null) { + return null; + } + final TextRange range = originalContext.getTextRange(); + final PsiElement originalAnchor = + CodeInsightUtil.findElementInRange(copy, range.getStartOffset(), range.getEndOffset(), originalContext.getClass()); + //todo before this or super, not found etc + final PsiElement anchor = RefactoringUtil.getParentStatement(originalAnchor, false); + final PsiElement container = anchor.getParent(); + final PsiElement firstElementCopy = container.addRangeBefore(elements[0], elements[elements.length - 1], anchor); + final PsiElement[] elementsCopy = CodeInsightUtil.findStatementsInRange(copy, + firstElementCopy.getTextRange().getStartOffset(), + anchor.getTextRange().getStartOffset()); + if (elementsCopy[elementsCopy.length - 1] instanceof PsiExpressionStatement) { + final PsiExpression expr = ((PsiExpressionStatement)elementsCopy[elementsCopy.length - 1]).getExpression(); + if (!(expr instanceof PsiAssignmentExpression)) { + final PsiType expressionType = expr.getType(); + if (expressionType != null && expressionType != PsiType.VOID) { + final String uniqueResultName = JavaCodeStyleManager.getInstance(project).suggestUniqueVariableName("result", elementsCopy[0], true); + final String statementText = expressionType.getCanonicalText() + " " + uniqueResultName + " = " + expr.getText() + ";"; + elementsCopy[elementsCopy.length - 1] = elementsCopy[elementsCopy.length - 1] + .replace(elementFactory.createStatementFromText(statementText, elementsCopy[elementsCopy.length - 1])); + } + } + } + + LOG.assertTrue(elementsCopy[0].getParent() == container, "element: " + elementsCopy[0].getText() + "; container: " + container.getText()); + final int startOffsetInContainer = elementsCopy[0].getStartOffsetInParent(); + + final ControlFlow controlFlow; + try { + controlFlow = ControlFlowFactory.getInstance(project).getControlFlow(container, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance()); + } + catch (AnalysisCanceledException e) { + return null; + } + + List<PsiVariable> variables = ControlFlowUtil.getUsedVariables(controlFlow, + controlFlow.getStartOffset(elementsCopy[0]), + controlFlow.getEndOffset(elementsCopy[elementsCopy.length - 1])); + + variables = ContainerUtil.filter(variables, new Condition<PsiVariable>() { + @Override + public boolean value(PsiVariable variable) { + final PsiElement variableScope = variable instanceof PsiParameter ? ((PsiParameter)variable).getDeclarationScope() + : PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class, PsiForStatement.class); + return variableScope != null && PsiTreeUtil.isAncestor(variableScope, elementsCopy[elementsCopy.length - 1], false); + } + }); + + + final String outputVariables = StringUtil.join(variables, new Function<PsiVariable, String>() { + @Override + public String fun(PsiVariable variable) { + return "\"variable: \" + " + variable.getName(); + } + }, " +"); + PsiStatement outStatement = elementFactory.createStatementFromText("System.out.println(" + outputVariables + ");", anchor); + outStatement = (PsiStatement)container.addAfter(outStatement, elementsCopy[elementsCopy.length - 1]); + + copy.accept(new JavaRecursiveElementWalkingVisitor() { + private void makePublic(PsiMember method) { + if (method.hasModifierProperty(PsiModifier.PRIVATE)) { + VisibilityUtil.setVisibility(method.getModifierList(), PsiModifier.PUBLIC); + } + } + + @Override + public void visitMethod(PsiMethod method) { + super.visitMethod(method); + makePublic(method); + } + + @Override + public void visitField(PsiField field) { + super.visitField(field); + makePublic(field); + } + }); + + final ExtractMethodObjectProcessor extractMethodObjectProcessor = new ExtractMethodObjectProcessor(project, null, elementsCopy, "") { + @Override + protected AbstractExtractDialog createExtractMethodObjectDialog(MyExtractMethodProcessor processor) { + return new LightExtractMethodObjectDialog(this, methodName); + } + }; + extractMethodObjectProcessor.getExtractProcessor().setShowErrorDialogs(false); + + final ExtractMethodObjectProcessor.MyExtractMethodProcessor extractProcessor = extractMethodObjectProcessor.getExtractProcessor(); + if (extractProcessor.prepare()) { + if (extractProcessor.showDialog()) { + try { + extractProcessor.doExtract(); + final UsageInfo[] usages = extractMethodObjectProcessor.findUsages(); + extractMethodObjectProcessor.performRefactoring(usages); + extractMethodObjectProcessor.runChangeSignature(); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + if (extractMethodObjectProcessor.isCreateInnerClass()) { + extractMethodObjectProcessor.changeInstanceAccess(project); + } + final PsiElement method = extractMethodObjectProcessor.getMethod(); + LOG.assertTrue(method != null); + method.delete(); + } + } else { + return null; + } + + final int startOffset = startOffsetInContainer + container.getTextRange().getStartOffset(); + final String generatedCall = copy.getText().substring(startOffset, outStatement.getTextOffset()); + return new ExtractedData(generatedCall, + (PsiClass)CodeStyleManager.getInstance(project).reformat(extractMethodObjectProcessor.getInnerClass()), + originalAnchor); + } + + + private static class LightExtractMethodObjectDialog implements AbstractExtractDialog { + private final ExtractMethodObjectProcessor myProcessor; + private final String myMethodName; + + public LightExtractMethodObjectDialog(ExtractMethodObjectProcessor processor, String methodName) { + myProcessor = processor; + myMethodName = methodName; + } + + @Override + public String getChosenMethodName() { + return myMethodName; + } + + @Override + public VariableData[] getChosenParameters() { + final InputVariables inputVariables = myProcessor.getExtractProcessor().getInputVariables(); + return inputVariables.getInputVariables().toArray(new VariableData[inputVariables.getInputVariables().size()]); + } + + @Override + public String getVisibility() { + return PsiModifier.PUBLIC; + } + + @Override + public boolean isMakeStatic() { + return false; + } + + @Override + public boolean isChainedConstructor() { + return false; + } + + @Override + public void show() {} + + @Override + public boolean isOK() { + return true; + } + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectDialog.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectDialog.java index fddd19bb4630..f79280fd1365 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectDialog.java @@ -19,6 +19,7 @@ import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.psi.*; @@ -44,7 +45,7 @@ import java.awt.event.ActionListener; import java.util.Enumeration; -public class ExtractMethodObjectDialog extends AbstractExtractDialog { +public class ExtractMethodObjectDialog extends DialogWrapper implements AbstractExtractDialog { private final Project myProject; private final PsiType myReturnType; private final PsiTypeParameterList myTypeParameterList; @@ -86,7 +87,7 @@ public class ExtractMethodObjectDialog extends AbstractExtractDialog { public ExtractMethodObjectDialog(Project project, PsiClass targetClass, final InputVariables inputVariables, PsiType returnType, PsiTypeParameterList typeParameterList, PsiType[] exceptions, boolean isStatic, boolean canBeStatic, final PsiElement[] elementsToExtract, final boolean multipleExitPoints) { - super(project); + super(project, true); myProject = project; myTargetClass = targetClass; myReturnType = returnType; diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectHandler.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectHandler.java index d8fb3fd6ef87..459a7030457f 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectHandler.java @@ -30,9 +30,7 @@ import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pass; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; +import com.intellij.psi.*; import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringActionHandler; @@ -55,7 +53,10 @@ public class ExtractMethodObjectHandler implements RefactoringActionHandler { }); } - private void invokeOnElements(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file, @NotNull PsiElement[] elements) { + private static void invokeOnElements(@NotNull final Project project, + @NotNull final Editor editor, + @NotNull PsiFile file, + @NotNull PsiElement[] elements) { if (elements.length == 0) { String message = RefactoringBundle .getCannotRefactorMessage(RefactoringBundle.message("selected.block.should.represent.a.set.of.statements.or.an.expression")); @@ -63,17 +64,18 @@ public class ExtractMethodObjectHandler implements RefactoringActionHandler { return; } - final ExtractMethodObjectProcessor processor = new ExtractMethodObjectProcessor(project, editor, elements, ""); - final ExtractMethodObjectProcessor.MyExtractMethodProcessor extractProcessor = processor.getExtractProcessor(); try { - if (!extractProcessor.prepare()) return; + extractMethodObject(project, editor, new ExtractMethodObjectProcessor(project, editor, elements, "")); } catch (PrepareFailedException e) { CommonRefactoringUtil.showErrorHint(project, editor, e.getMessage(), ExtractMethodObjectProcessor.REFACTORING_NAME, HelpID.EXTRACT_METHOD_OBJECT); ExtractMethodHandler.highlightPrepareError(e, file, editor, project); - return; } + } + static void extractMethodObject(Project project, Editor editor, ExtractMethodObjectProcessor processor) throws PrepareFailedException { + final ExtractMethodObjectProcessor.MyExtractMethodProcessor extractProcessor = processor.getExtractProcessor(); + if (!extractProcessor.prepare()) return; if (!CommonRefactoringUtil.checkReadOnlyStatus(project, extractProcessor.getTargetClass().getContainingFile())) return; if (extractProcessor.showDialog()) { run(project, editor, processor, extractProcessor); @@ -81,11 +83,16 @@ public class ExtractMethodObjectHandler implements RefactoringActionHandler { } public static void run(@NotNull final Project project, - @NotNull final Editor editor, + final Editor editor, @NotNull final ExtractMethodObjectProcessor processor, @NotNull final ExtractMethodObjectProcessor.MyExtractMethodProcessor extractProcessor) { - final int offset = editor.getCaretModel().getOffset(); - final RangeMarker marker = editor.getDocument().createRangeMarker(new TextRange(offset, offset)); + final RangeMarker marker; + if (editor != null) { + final int offset = editor.getCaretModel().getOffset(); + marker = editor.getDocument().createRangeMarker(new TextRange(offset, offset)); + } else { + marker = null; + } CommandProcessor.getInstance().executeCommand(project, new Runnable() { public void run() { PostprocessReformattingAspect.getInstance(project).postponeFormattingInside(new Runnable() { @@ -98,7 +105,11 @@ public class ExtractMethodObjectHandler implements RefactoringActionHandler { } }); processor.run(); - processor.runChangeSignature(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + processor.runChangeSignature(); + } + }); } catch (IncorrectOperationException e) { LOG.error(e); @@ -110,7 +121,9 @@ public class ExtractMethodObjectHandler implements RefactoringActionHandler { if (processor.isCreateInnerClass()) { processor.moveUsedMethodsToInner(); PsiDocumentManager.getInstance(project).commitAllDocuments(); - DuplicatesImpl.processDuplicates(extractProcessor, project, editor); + if (editor != null) { + DuplicatesImpl.processDuplicates(extractProcessor, project, editor); + } } ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override @@ -125,9 +138,11 @@ public class ExtractMethodObjectHandler implements RefactoringActionHandler { }); } }, ExtractMethodObjectProcessor.REFACTORING_NAME, ExtractMethodObjectProcessor.REFACTORING_NAME); - editor.getCaretModel().moveToOffset(marker.getStartOffset()); - marker.dispose(); - editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + if (editor != null) { + editor.getCaretModel().moveToOffset(marker.getStartOffset()); + marker.dispose(); + editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + } } public void invoke(@NotNull final Project project, @NotNull final PsiElement[] elements, final DataContext dataContext) { diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java index 7f95c49c65b3..49f4b2727cee 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java @@ -37,10 +37,13 @@ import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.controlFlow.ControlFlowUtil; import com.intellij.psi.impl.source.PsiImmediateClassType; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.PsiUtilCore; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor; @@ -52,6 +55,7 @@ import com.intellij.refactoring.ui.MemberSelectionPanel; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.refactoring.util.classMembers.MemberInfo; import com.intellij.refactoring.util.duplicates.Match; +import com.intellij.testFramework.LightVirtualFile; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.usageView.UsageViewUtil; @@ -82,7 +86,7 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { private boolean myMadeStatic = false; private final Set<MethodToMoveUsageInfo> myUsages = new LinkedHashSet<MethodToMoveUsageInfo>(); private PsiClass myInnerClass; - private ChangeSignatureProcessor myChangeSignatureProcessor; + private boolean myChangeReturnType; private Runnable myCopyMethodToInner; public ExtractMethodObjectProcessor(Project project, Editor editor, PsiElement[] elements, final String innerClassName) { @@ -100,8 +104,12 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { @NotNull protected UsageInfo[] findUsages() { final ArrayList<UsageInfo> result = new ArrayList<UsageInfo>(); + final PsiClass containingClass = getMethod().getContainingClass(); + final SearchScope scope = PsiUtilCore.getVirtualFile(containingClass) == null + ? new LocalSearchScope(containingClass) + : GlobalSearchScope.projectScope(myProject); PsiReference[] refs = - ReferencesSearch.search(getMethod(), GlobalSearchScope.projectScope(myProject), false).toArray(PsiReference.EMPTY_ARRAY); + ReferencesSearch.search(getMethod(), scope, false).toArray(PsiReference.EMPTY_ARRAY); for (PsiReference ref : refs) { final PsiElement element = ref.getElement(); if (element != null && element.isValid()) { @@ -141,7 +149,7 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { return UsageViewUtil.removeDuplicatedUsages(usageInfos); } - protected void performRefactoring(final UsageInfo[] usages) { + public void performRefactoring(final UsageInfo[] usages) { try { if (isCreateInnerClass()) { myInnerClass = (PsiClass)getMethod().getContainingClass().add(myElementFactory.createClass(getInnerClassName())); @@ -258,12 +266,6 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { myInnerClass.add(GenerateMembersUtil.generateGetterPrototype(field)); } - PsiParameter[] params = getMethod().getParameterList().getParameters(); - ParameterInfoImpl[] infos = new ParameterInfoImpl[params.length]; - for (int i = 0; i < params.length; i++) { - PsiParameter param = params[i]; - infos[i] = new ParameterInfoImpl(i, param.getName(), param.getType()); - } final PsiCodeBlock body = getMethod().getBody(); LOG.assertTrue(body != null); final LinkedHashSet<PsiLocalVariable> vars = new LinkedHashSet<PsiLocalVariable>(); @@ -320,7 +322,7 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { for (PsiElement declaredElement : declaredElements) { if (declaredElement instanceof PsiVariable) { for (PsiVariable variable : outputVariables) { - PsiLocalVariable var = (PsiLocalVariable)declaredElement; + PsiVariable var = (PsiVariable)declaredElement; if (Comparing.strEqual(var.getName(), variable.getName())) { final PsiExpression initializer = var.getInitializer(); if (initializer == null) { @@ -385,23 +387,25 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { } } - myChangeSignatureProcessor = new ChangeSignatureProcessor(myProject, getMethod(), false, null, getMethod().getName(), - new PsiImmediateClassType(myInnerClass, PsiSubstitutor.EMPTY), infos); + myChangeReturnType = true; } void runChangeSignature() { - if (myChangeSignatureProcessor != null) { - myChangeSignatureProcessor.run(); - } if (myCopyMethodToInner != null) { - ApplicationManager.getApplication().runWriteAction(myCopyMethodToInner); + myCopyMethodToInner.run(); + } + if (myChangeReturnType) { + final PsiTypeElement typeElement = ((PsiLocalVariable)((PsiDeclarationStatement)JavaPsiFacade.getElementFactory(myProject) + .createStatementFromText(myInnerClassName + " l =null;", myInnerClass)).getDeclaredElements()[0]).getTypeElement(); + final PsiTypeElement innerMethodReturnTypeElement = myInnerMethod.getReturnTypeElement(); + LOG.assertTrue(innerMethodReturnTypeElement != null); + innerMethodReturnTypeElement.replace(typeElement); } } private String getPureName(PsiVariable var) { final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(myProject); - final VariableKind kind = var instanceof PsiLocalVariable ? VariableKind.LOCAL_VARIABLE : VariableKind.PARAMETER; - return styleManager.variableNameToPropertyName(var.getName(), kind); + return styleManager.variableNameToPropertyName(var.getName(), styleManager.getVariableKind(var)); } public PsiExpression processMethodDeclaration( PsiExpressionList expressionList) throws IncorrectOperationException { @@ -624,6 +628,22 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { return myExtractProcessor; } + protected AbstractExtractDialog createExtractMethodObjectDialog(final MyExtractMethodProcessor processor) { + return new ExtractMethodObjectDialog(myProject, processor.getTargetClass(), processor.getInputVariables(), processor.getReturnType(), + processor.getTypeParameterList(), + processor.getThrownExceptions(), processor.isStatic(), processor.isCanBeStatic(), + processor.getElements(), myMultipleExitPoints){ + @Override + protected boolean isUsedAfter(PsiVariable variable) { + return ArrayUtil.find(processor.getOutputVariables(), variable) != -1; + } + }; + } + + public PsiClass getInnerClass() { + return myInnerClass; + } + public class MyExtractMethodProcessor extends ExtractMethodProcessor { public MyExtractMethodProcessor(Project project, @@ -640,19 +660,13 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { @Override protected void apply(final AbstractExtractDialog dialog) { super.apply(dialog); - myCreateInnerClass = ((ExtractMethodObjectDialog)dialog).createInnerClass(); + myCreateInnerClass = !(dialog instanceof ExtractMethodObjectDialog) || ((ExtractMethodObjectDialog)dialog).createInnerClass(); myInnerClassName = myCreateInnerClass ? StringUtil.capitalize(dialog.getChosenMethodName()) : dialog.getChosenMethodName(); } @Override protected AbstractExtractDialog createExtractMethodDialog(final boolean direct) { - return new ExtractMethodObjectDialog(myProject, myTargetClass, myInputVariables, myReturnType, myTypeParameterList, - myThrownExceptions, myStatic, myCanBeStatic, myElements, myMultipleExitPoints){ - @Override - protected boolean isUsedAfter(PsiVariable variable) { - return ArrayUtil.find(myOutputVariables, variable) != -1; - } - }; + return createExtractMethodObjectDialog(this); } @Override diff --git a/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationDialog.java b/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationDialog.java index 32e4992fe744..efff2b7790cd 100644 --- a/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationDialog.java @@ -33,7 +33,6 @@ import com.intellij.refactoring.ui.NameSuggestionsField; import com.intellij.refactoring.ui.RefactoringDialog; import com.intellij.refactoring.util.classMembers.InterfaceMemberDependencyGraph; import com.intellij.refactoring.util.classMembers.MemberInfo; -import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,6 +44,7 @@ import java.awt.event.ItemListener; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; public class InheritanceToDelegationDialog extends RefactoringDialog { private final PsiClass[] mySuperClasses; diff --git a/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationHandler.java b/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationHandler.java index c9daa8c1bbdb..7cc464bcb710 100644 --- a/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationHandler.java @@ -41,13 +41,10 @@ import com.intellij.refactoring.util.RefactoringHierarchyUtil; import com.intellij.refactoring.util.RefactoringMessageUtil; import com.intellij.refactoring.util.classMembers.MemberInfo; import com.intellij.refactoring.util.classMembers.MemberInfoStorage; -import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import java.util.*; public class InheritanceToDelegationHandler implements RefactoringActionHandler { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.inheritanceToDelegation.InheritanceToDelegationHandler"); @@ -106,23 +103,26 @@ public class InheritanceToDelegationHandler implements RefactoringActionHandler if (!CommonRefactoringUtil.checkReadOnlyStatus(project, aClass)) return; - final PsiClass[] bases = aClass.getSupers(); + PsiClass[] bases = aClass.getSupers(); @NonNls final String javaLangObject = CommonClassNames.JAVA_LANG_OBJECT; + if (bases.length == 0 || bases.length == 1 && javaLangObject.equals(bases[0].getQualifiedName())) { String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("class.does.not.have.base.classes.or.interfaces", aClass.getQualifiedName())); CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INHERITANCE_TO_DELEGATION); return; } - final HashMap<PsiClass, Collection<MemberInfo>> basesToMemberInfos = new HashMap<PsiClass, Collection<MemberInfo>>(); + final HashMap<PsiClass, Collection<MemberInfo>> basesToMemberInfos = new LinkedHashMap<PsiClass, Collection<MemberInfo>>(); for (PsiClass base : bases) { + if (javaLangObject.equals(base.getQualifiedName())) continue; basesToMemberInfos.put(base, createBaseClassMemberInfos(base)); } + final Set<PsiClass> baseClasses = basesToMemberInfos.keySet(); new InheritanceToDelegationDialog(project, aClass, - bases, basesToMemberInfos).show(); + baseClasses.toArray(new PsiClass[baseClasses.size()]), basesToMemberInfos).show(); } private static List<MemberInfo> createBaseClassMemberInfos(PsiClass baseClass) { diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java index ed08349519a7..0cc9819c4574 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java @@ -30,10 +30,7 @@ import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -1045,13 +1042,13 @@ public class RefactoringUtil { } public static void fixJavadocsForParams(PsiMethod method, Set<PsiParameter> newParameters) throws IncorrectOperationException { - fixJavadocsForParams(method, newParameters, Condition.FALSE); + fixJavadocsForParams(method, newParameters, Conditions.<Pair<PsiParameter,String>>alwaysFalse()); } public static void fixJavadocsForParams(PsiMethod method, Set<PsiParameter> newParameters, Condition<Pair<PsiParameter, String>> eqCondition) throws IncorrectOperationException { - fixJavadocsForParams(method, newParameters, eqCondition, Condition.TRUE); + fixJavadocsForParams(method, newParameters, eqCondition, Conditions.<String>alwaysTrue()); } public static void fixJavadocsForParams(PsiMethod method, @@ -1245,7 +1242,7 @@ public class RefactoringUtil { @Nullable public static PsiTypeParameterList createTypeParameterListWithUsedTypeParameters(@Nullable final PsiTypeParameterList fromList, @NotNull final PsiElement... elements) { - return createTypeParameterListWithUsedTypeParameters(fromList, Condition.TRUE, elements); + return createTypeParameterListWithUsedTypeParameters(fromList, Conditions.<PsiTypeParameter>alwaysTrue(), elements); } @Nullable @@ -1290,7 +1287,7 @@ public class RefactoringUtil { } public static void collectTypeParameters(final Set<PsiTypeParameter> used, final PsiElement element) { - collectTypeParameters(used, element, Condition.TRUE); + collectTypeParameters(used, element, Conditions.<PsiTypeParameter>alwaysTrue()); } public static void collectTypeParameters(final Set<PsiTypeParameter> used, final PsiElement element, final Condition<PsiTypeParameter> filter) { |