diff options
Diffstat (limited to 'java/java-impl/src/com')
46 files changed, 1507 insertions, 380 deletions
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 49379c2c4f3e..2a9fc2f4a79f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.TailType; import com.intellij.codeInsight.completion.scope.CompletionElement; import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor; import com.intellij.codeInsight.editorActions.wordSelection.DocTagSelectioner; +import com.intellij.codeInsight.javadoc.JavaDocUtil; import com.intellij.codeInsight.lookup.*; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.SuppressionUtil; @@ -391,16 +392,19 @@ public class JavaDocCompletionContributor extends CompletionContributor { private static void shortenReferences(final Project project, final Editor editor, InsertionContext context, int offset) { PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); final PsiElement element = context.getFile().findElementAt(offset); - final PsiDocTagValue tagValue = PsiTreeUtil.getParentOfType(element, PsiDocTagValue.class); - if (tagValue != null) { - try { - JavaCodeStyleManager.getInstance(project).shortenClassReferences(tagValue); - } - catch (IncorrectOperationException e) { - LOG.error(e); + final PsiDocComment docComment = PsiTreeUtil.getParentOfType(element, PsiDocComment.class); + if (!JavaDocUtil.isInsidePackageInfo(docComment)) { + final PsiDocTagValue tagValue = PsiTreeUtil.getParentOfType(element, PsiDocTagValue.class); + if (tagValue != null) { + try { + JavaCodeStyleManager.getInstance(project).shortenClassReferences(tagValue); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } } + PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments(); } - PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments(); } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java index 7015004b7340..351eca4857fd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java @@ -15,10 +15,7 @@ */ package com.intellij.codeInsight.completion; -import com.intellij.codeInsight.generation.GenerateMembersUtil; -import com.intellij.codeInsight.generation.OverrideImplementExploreUtil; -import com.intellij.codeInsight.generation.OverrideImplementUtil; -import com.intellij.codeInsight.generation.PsiGenerationInfo; +import com.intellij.codeInsight.generation.*; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.icons.AllIcons; @@ -35,6 +32,7 @@ import com.intellij.util.containers.ContainerUtil; import javax.swing.*; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -70,8 +68,8 @@ public class JavaGenerateMemberCompletionContributor { List<PsiMethod> prototypes = ContainerUtil.newArrayList(); for (PsiField field : parent.getFields()) { if (!(field instanceof PsiEnumConstant)) { - prototypes.add(GenerateMembersUtil.generateGetterPrototype(field)); - prototypes.add(GenerateMembersUtil.generateSetterPrototype(field)); + Collections.addAll(prototypes, GetterSetterPrototypeProvider.generateGetterSetters(field, true)); + Collections.addAll(prototypes, GetterSetterPrototypeProvider.generateGetterSetters(field, false)); } } for (final PsiMethod prototype : prototypes) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java index 29906bbde605..c0f82668f74a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java @@ -39,7 +39,11 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type private boolean myMayNeedExplicitTypeParameters; public JavaMethodCallElement(@NotNull PsiMethod method) { - super(method, method.getName()); + this(method, method.getName()); + } + + public JavaMethodCallElement(@NotNull PsiMethod method, String methodName) { + super(method, methodName); myMethod = method; myHelper = null; myContainingClass = method.getContainingClass(); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java index f169ccd8aa56..4fd7df6c7e2e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java @@ -25,6 +25,7 @@ import com.intellij.openapi.editor.EditorModificationUtil; import com.intellij.openapi.project.Project; 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.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil; import com.intellij.psi.util.PsiUtil; @@ -52,18 +53,25 @@ public class LambdaCompletionProvider extends CompletionProvider<CompletionParam final Project project = method.getProject(); final PsiElement originalPosition = parameters.getOriginalPosition(); final JVMElementFactory jvmElementFactory = originalPosition != null ? JVMElementFactories.getFactory(originalPosition.getLanguage(), project) : null; + final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project); if (jvmElementFactory != null) { final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(method, PsiUtil.resolveGenericsClassInType(functionalInterfaceType)); - final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); - params = GenerateMembersUtil.overriddenParameters(params, jvmElementFactory, codeStyleManager, substitutor, originalPosition); + params = GenerateMembersUtil.overriddenParameters(params, jvmElementFactory, javaCodeStyleManager, substitutor, originalPosition); } - final String paramsString = params.length == 1 ? params[0].getName() : "(" + StringUtil.join(params, new Function<PsiParameter, String>() { + String paramsString = + params.length == 1 ? getParamName(params[0], javaCodeStyleManager, originalPosition) : "(" + StringUtil.join(params, new Function<PsiParameter, String>() { @Override public String fun(PsiParameter parameter) { - return parameter.getName(); + return getParamName(parameter, javaCodeStyleManager, originalPosition); } - }, ",") + ")"; + }, ",") + ")"; + + final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project); + PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)JavaPsiFacade.getElementFactory(project) + .createExpressionFromText(paramsString + " -> {}", null); + lambdaExpression = (PsiLambdaExpression)codeStyleManager.reformat(lambdaExpression); + paramsString = lambdaExpression.getParameterList().getText(); final LookupElementBuilder builder = LookupElementBuilder.create(paramsString).withPresentableText(paramsString + " -> {}").withInsertHandler(new InsertHandler<LookupElement>() { @Override @@ -77,4 +85,8 @@ public class LambdaCompletionProvider extends CompletionProvider<CompletionParam } } } + + private static String getParamName(PsiParameter param, JavaCodeStyleManager javaCodeStyleManager, PsiElement originalPosition) { + return javaCodeStyleManager.suggestUniqueVariableName(param.getName(), originalPosition, true); + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/MethodReferenceCompletionProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/MethodReferenceCompletionProvider.java index e83f0ef38c3c..494ed110b254 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/MethodReferenceCompletionProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/MethodReferenceCompletionProvider.java @@ -68,7 +68,7 @@ public class MethodReferenceCompletionProvider extends CompletionProvider<Comple final PsiElement resolve = referenceExpression.resolve(); if (resolve != null && PsiEquivalenceUtil.areElementsEquivalent(element, resolve) && PsiMethodReferenceUtil.checkMethodReferenceContext(referenceExpression, resolve, functionalType) == null) { - result.addElement(new JavaMethodReferenceElement((PsiMethod)element, refPlace, referenceExpression)); + result.addElement(new JavaMethodReferenceElement((PsiMethod)element, refPlace)); } } finally { @@ -80,19 +80,20 @@ public class MethodReferenceCompletionProvider extends CompletionProvider<Comple } private PsiMethodReferenceExpression createMethodReferenceExpression(PsiMethod method) { + PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(method.getProject()); if (refPlace instanceof PsiMethodReferenceExpression) { final PsiMethodReferenceExpression referenceExpression = (PsiMethodReferenceExpression)refPlace.copy(); final PsiElement referenceNameElement = referenceExpression.getReferenceNameElement(); LOG.assertTrue(referenceNameElement != null, referenceExpression); - referenceNameElement.replace(JavaPsiFacade.getElementFactory(method.getProject()).createIdentifier(method.getName())); + referenceNameElement.replace(method.isConstructor() ? elementFactory.createKeyword("new") : elementFactory.createIdentifier(method.getName())); return referenceExpression; } else if (method.hasModifierProperty(PsiModifier.STATIC)) { final PsiClass aClass = method.getContainingClass(); LOG.assertTrue(aClass != null); final String qualifiedName = aClass.getQualifiedName(); - return (PsiMethodReferenceExpression)JavaPsiFacade.getElementFactory(method.getProject()).createExpressionFromText( - qualifiedName + "::" + method.getName(), refPlace); + return (PsiMethodReferenceExpression)elementFactory.createExpressionFromText( + qualifiedName + "::" + (method.isConstructor() ? "new" : method.getName()), refPlace); } else { return null; @@ -113,13 +114,11 @@ public class MethodReferenceCompletionProvider extends CompletionProvider<Comple private static class JavaMethodReferenceElement extends JavaMethodCallElement { private final PsiMethod myMethod; private final PsiElement myRefPlace; - private PsiMethodReferenceExpression myReferenceExpression; - public JavaMethodReferenceElement(PsiMethod method, PsiElement refPlace, PsiMethodReferenceExpression referenceExpression) { - super(method); + public JavaMethodReferenceElement(PsiMethod method, PsiElement refPlace) { + super(method, method.isConstructor() ? "new" : method.getName()); myMethod = method; myRefPlace = refPlace; - myReferenceExpression = referenceExpression; } @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java index abe9368374e8..9e8684899939 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java @@ -475,7 +475,7 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction { } else { while (true) { final String paramName = idx > 0 ? "T" + idx : "T"; - if (!typeParamNames.contains(paramName)) { + if (typeParamNames.add(paramName)) { targetClass.getTypeParameterList().add(factory.createTypeParameterFromText(paramName, null)); break; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java index 209dde6cf4ea..897c6f80a571 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.generation.GenerateMembersUtil; +import com.intellij.codeInsight.generation.GetterSetterPrototypeProvider; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.LowPriorityAction; import com.intellij.openapi.editor.Editor; @@ -29,6 +30,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -115,10 +117,10 @@ public class CreateGetterOrSetterFix implements IntentionAction, LowPriorityActi PsiClass aClass = myField.getContainingClass(); final List<PsiMethod> methods = new ArrayList<PsiMethod>(); if (myCreateGetter) { - methods.add(GenerateMembersUtil.generateGetterPrototype(myField)); + Collections.addAll(methods, GetterSetterPrototypeProvider.generateGetterSetters(myField, true)); } if (myCreateSetter) { - methods.add(GenerateMembersUtil.generateSetterPrototype(myField)); + Collections.addAll(methods, GetterSetterPrototypeProvider.generateGetterSetters(myField, false)); } for (PsiMethod method : methods) { aClass.add(method); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java index 55fe7664d0b0..333ca47b014c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java @@ -67,9 +67,8 @@ public class CreateInnerClassFromNewFix extends CreateClassFromNewFix { } created = (PsiClass)targetClass.add(created); - setupClassFromNewExpression(created, newExpression); - setupGenericParameters(created, ref); + setupClassFromNewExpression(created, newExpression); } private static boolean isInThisOrSuperCall(PsiNewExpression newExpression) { diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithUtil.java index 046a9b7cea0a..2439aafc1e87 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithUtil.java @@ -28,6 +28,7 @@ import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.PsiUtilBase; import com.intellij.psi.util.PsiUtilCore; +import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -59,7 +60,7 @@ public class SurroundWithUtil { PsiExpressionStatement assignment = (PsiExpressionStatement)factory.createStatementFromText(name + "=x;", null); assignment = (PsiExpressionStatement)CodeStyleManager.getInstance(psiManager.getProject()).reformat(assignment); PsiAssignmentExpression expr = (PsiAssignmentExpression)assignment.getExpression(); - expr.getRExpression().replace(initializer); + expr.getRExpression().replace(RefactoringUtil.convertInitializerToNormalExpression(initializer, var.getType())); assignment = (PsiExpressionStatement)block.addAfter(assignment, declaration); array.add(assignment); } diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.java index 4756a5b25a47..5ccdc398684f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.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. @@ -29,6 +29,7 @@ import com.intellij.psi.*; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.util.RefactoringChangeUtil; +import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -126,9 +127,7 @@ public abstract class BaseMoveInitializerToMethodAction extends PsiElementBaseIn final PsiExpressionStatement statement = (PsiExpressionStatement)factory.createStatementFromText(field.getName() + " = y;", codeBlock); PsiExpression initializer = field.getInitializer(); - if (initializer instanceof PsiArrayInitializerExpression) { - initializer = arrayInitializerToNewExpression((PsiArrayInitializerExpression)initializer, factory, codeBlock); - } + initializer = RefactoringUtil.convertInitializerToNormalExpression(initializer, field.getType()); final PsiAssignmentExpression expression = (PsiAssignmentExpression)statement.getExpression(); expression.getRExpression().replace(initializer); @@ -158,15 +157,6 @@ public abstract class BaseMoveInitializerToMethodAction extends PsiElementBaseIn return false; } - private static PsiExpression arrayInitializerToNewExpression(@NotNull PsiArrayInitializerExpression initializer, - @NotNull PsiElementFactory factory, - @NotNull PsiElement context) { - final PsiType type = initializer.getType(); - final PsiNewExpression newExpression = (PsiNewExpression)factory.createExpressionFromText("new " + type.getCanonicalText() + "{}", context); - newExpression.getArrayInitializer().replace(initializer); - return newExpression; - } - private static boolean containsReference(final @NotNull PsiElement element, final @NotNull PsiField field) { final Ref<Boolean> result = new Ref<Boolean>(Boolean.FALSE); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CopyAbstractMethodImplementationHandler.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CopyAbstractMethodImplementationHandler.java index ddddf94430f7..6f6dcf4d4d6f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CopyAbstractMethodImplementationHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CopyAbstractMethodImplementationHandler.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. @@ -20,6 +20,7 @@ import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.generation.GenerateMembersUtil; import com.intellij.codeInsight.generation.OverrideImplementUtil; import com.intellij.ide.util.MethodCellRenderer; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; @@ -38,6 +39,7 @@ import com.intellij.psi.util.PsiUtilCore; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.ui.components.JBList; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.util.*; @@ -66,7 +68,12 @@ public class CopyAbstractMethodImplementationHandler { ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { - searchExistingImplementations(); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + searchExistingImplementations(); + } + }); } }, CodeInsightBundle.message("searching.for.implementations"), false, myProject); if (mySourceMethods.isEmpty()) { @@ -152,7 +159,7 @@ public class CopyAbstractMethodImplementationHandler { final List<PsiMethod> generatedMethods = new ArrayList<PsiMethod>(); new WriteCommandAction(myProject, getTargetFiles()) { @Override - protected void run(final Result result) throws Throwable { + protected void run(@NotNull final Result result) throws Throwable { for (PsiEnumConstant enumConstant : myTargetEnumConstants) { PsiClass initializingClass = enumConstant.getOrCreateInitializingClass(); myTargetClasses.add(initializingClass); @@ -186,7 +193,7 @@ public class CopyAbstractMethodImplementationHandler { } } }.execute(); - if (generatedMethods.size() > 0) { + if (!generatedMethods.isEmpty()) { PsiMethod target = generatedMethods.get(0); PsiFile psiFile = target.getContainingFile(); FileEditorManager fileEditorManager = FileEditorManager.getInstance(psiFile.getProject()); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java index 8c1da6252efb..9ea64d81463b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java @@ -25,6 +25,7 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -119,12 +120,7 @@ public class SplitDeclarationAction extends PsiElementBaseIntentionAction { statement = (PsiExpressionStatement)CodeStyleManager.getInstance(project).reformat(statement); PsiAssignmentExpression assignment = (PsiAssignmentExpression)statement.getExpression(); PsiExpression initializer = var.getInitializer(); - PsiExpression rExpression = initializer; - if (initializer instanceof PsiArrayInitializerExpression && var.getType() instanceof PsiArrayType) { - rExpression = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createExpressionFromText( - "new " + var.getTypeElement().getText() + " " + initializer.getText(), null - ); - } + PsiExpression rExpression = RefactoringUtil.convertInitializerToNormalExpression(initializer, var.getType()); assignment.getRExpression().replace(rExpression); initializer.delete(); diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java index 2142c8fd33da..7e168e23dd1e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java @@ -106,21 +106,21 @@ public abstract class JavaPostfixTemplatesUtils { public static Condition<PsiElement> IS_THROWABLE = new Condition<PsiElement>() { @Override public boolean value(PsiElement element) { - return element instanceof PsiExpression && isThrowable((((PsiExpression)element).getType())); + return element instanceof PsiExpression && isThrowable(((PsiExpression)element).getType()); } }; public static Condition<PsiElement> IS_NON_VOID = new Condition<PsiElement>() { @Override public boolean value(PsiElement element) { - return element instanceof PsiExpression && isNonVoid((((PsiExpression)element).getType())); + return element instanceof PsiExpression && isNonVoid(((PsiExpression)element).getType()); } }; public static Condition<PsiElement> IS_NOT_PRIMITIVE = new Condition<PsiElement>() { @Override public boolean value(PsiElement element) { - return element instanceof PsiExpression && isNotPrimitiveTypeExpression(((PsiExpression)element)); + return element instanceof PsiExpression && isNotPrimitiveTypeExpression((PsiExpression)element); } }; @@ -130,7 +130,7 @@ public abstract class JavaPostfixTemplatesUtils { if (!(element instanceof PsiExpression)) return false; PsiType type = ((PsiExpression)element).getType(); - return (isArray(type) || isIterable(type)); + return isArray(type) || isIterable(type); } }; diff --git a/java/java-impl/src/com/intellij/codeInspection/actions/ReplaceImplementsWithStaticImportAction.java b/java/java-impl/src/com/intellij/codeInspection/actions/ReplaceImplementsWithStaticImportAction.java index ce12094e74a3..5ced0c4fb766 100644 --- a/java/java-impl/src/com/intellij/codeInspection/actions/ReplaceImplementsWithStaticImportAction.java +++ b/java/java-impl/src/com/intellij/codeInspection/actions/ReplaceImplementsWithStaticImportAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 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. @@ -96,7 +96,7 @@ public class ReplaceImplementsWithStaticImportAction extends BaseIntentionAction JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_LANG_OBJECT, GlobalSearchScope.allScope(project)); if (objectClass == null) return false; methods.removeAll(Arrays.asList(objectClass.getMethods())); - if (methods.size() > 0) return false; + if (!methods.isEmpty()) return false; } else if (targetClass.getMethods().length > 0) { return false; @@ -122,7 +122,7 @@ public class ReplaceImplementsWithStaticImportAction extends BaseIntentionAction final PsiClass targetClass = (PsiClass)target; new WriteCommandAction(project, getText()) { @Override - protected void run(Result result) throws Throwable { + protected void run(@NotNull Result result) throws Throwable { for (PsiField constField : targetClass.getAllFields()) { final String fieldName = constField.getName(); final PsiClass containingClass = constField.getContainingClass(); @@ -159,30 +159,35 @@ public class ReplaceImplementsWithStaticImportAction extends BaseIntentionAction if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { - for (PsiField field : targetClass.getAllFields()) { - final PsiClass containingClass = field.getContainingClass(); - for (PsiReference reference : ReferencesSearch.search(field)) { - if (reference == null) { - continue; - } - final PsiElement refElement = reference.getElement(); - if (encodeQualifier(containingClass, reference, targetClass)) continue; - final PsiFile psiFile = refElement.getContainingFile(); - if (psiFile instanceof PsiJavaFile) { - Map<PsiField, Set<PsiReference>> references = refs.get(psiFile); - if (references == null) { - references = new HashMap<PsiField, Set<PsiReference>>(); - refs.put(psiFile, references); - } - Set<PsiReference> fieldsRefs = references.get(field); - if (fieldsRefs == null) { - fieldsRefs = new HashSet<PsiReference>(); - references.put(field, fieldsRefs); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + for (PsiField field : targetClass.getAllFields()) { + final PsiClass containingClass = field.getContainingClass(); + for (PsiReference reference : ReferencesSearch.search(field)) { + if (reference == null) { + continue; + } + final PsiElement refElement = reference.getElement(); + if (encodeQualifier(containingClass, reference, targetClass)) continue; + final PsiFile psiFile = refElement.getContainingFile(); + if (psiFile instanceof PsiJavaFile) { + Map<PsiField, Set<PsiReference>> references = refs.get(psiFile); + if (references == null) { + references = new HashMap<PsiField, Set<PsiReference>>(); + refs.put(psiFile, references); + } + Set<PsiReference> fieldsRefs = references.get(field); + if (fieldsRefs == null) { + fieldsRefs = new HashSet<PsiReference>(); + references.put(field, fieldsRefs); + } + fieldsRefs.add(reference); + } } - fieldsRefs.add(reference); } } - } + }); } }, FIND_CONSTANT_FIELD_USAGES, true, project)) { return; @@ -192,14 +197,19 @@ public class ReplaceImplementsWithStaticImportAction extends BaseIntentionAction if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { - for (PsiClass psiClass : DirectClassInheritorsSearch.search(targetClass)) { - PsiFile containingFile = psiClass.getContainingFile(); - if (!refs.containsKey(containingFile)) { - refs.put(containingFile, new HashMap<PsiField, Set<PsiReference>>()); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + for (PsiClass psiClass : DirectClassInheritorsSearch.search(targetClass)) { + PsiFile containingFile = psiClass.getContainingFile(); + if (!refs.containsKey(containingFile)) { + refs.put(containingFile, new HashMap<PsiField, Set<PsiReference>>()); + } + if (collectExtendsImplements(targetClass, psiClass.getExtendsList(), refs2Unimplement)) continue; + collectExtendsImplements(targetClass, psiClass.getImplementsList(), refs2Unimplement); + } } - if (collectExtendsImplements(targetClass, psiClass.getExtendsList(), refs2Unimplement)) continue; - collectExtendsImplements(targetClass, psiClass.getImplementsList(), refs2Unimplement); - } + }); } }, "Find references in implement/extends lists...", true, project)) { return; @@ -232,14 +242,19 @@ public class ReplaceImplementsWithStaticImportAction extends BaseIntentionAction if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable(){ @Override public void run() { - for (PsiFile psiFile : refs.keySet()) { - final Collection<PsiImportStatementBase> red = codeStyleManager.findRedundantImports((PsiJavaFile)psiFile); - if (red != null) { - for (PsiImportStatementBase statementBase : red) { - redundant.add(pointerManager.createSmartPsiElementPointer(statementBase)); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + for (PsiFile psiFile : refs.keySet()) { + final Collection<PsiImportStatementBase> red = codeStyleManager.findRedundantImports((PsiJavaFile)psiFile); + if (red != null) { + for (PsiImportStatementBase statementBase : red) { + redundant.add(pointerManager.createSmartPsiElementPointer(statementBase)); + } + } } } - } + }); } }, "Collect redundant imports...", true, project)) return; ApplicationManager.getApplication().runWriteAction(new Runnable() { diff --git a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java index ba5b40120a32..df37ce2a7267 100644 --- a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java @@ -100,7 +100,7 @@ public class JavaDocLocalInspection extends JavaDocLocalInspectionBase { InspectionsBundle.message("inspection.scope.for.title"), true), BorderFactory.createEmptyBorder(0, 3, 3, 3))); - final Hashtable<Integer, JLabel> sliderLabels = new Hashtable<Integer, JLabel>(); + final Hashtable<Integer, JComponent> sliderLabels = new Hashtable<Integer, JComponent>(); for (int i = 0; i < modifiers.length; i++) { sliderLabels.put(i + 1, new JLabel(modifiers[i])); } @@ -184,11 +184,11 @@ public class JavaDocLocalInspection extends JavaDocLocalInspectionBase { add(periodCheckBox, gc); final JCheckBox ignoreDuplicateThrowsCheckBox = new JCheckBox("Ignore duplicate throws tag", - IGNORE_DUPLICATED_THROWS); + getIgnoreDuplicatedThrows()); ignoreDuplicateThrowsCheckBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - IGNORE_DUPLICATED_THROWS = ignoreDuplicateThrowsCheckBox.isSelected(); + setIgnoreDuplicatedThrows(ignoreDuplicateThrowsCheckBox.isSelected()); } }); add(ignoreDuplicateThrowsCheckBox, gc); diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java b/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java index 73fcc83df646..b68b68b8b195 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.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. @@ -136,6 +136,7 @@ public final class PackageViewPane extends AbstractProjectViewPSIPane { return result; } + @NotNull @Override public PsiDirectory[] getSelectedDirectories() { List<PsiDirectory> directories = ContainerUtil.newArrayList(); @@ -194,6 +195,7 @@ public final class PackageViewPane extends AbstractProjectViewPSIPane { @Override public void addToolbarActions(DefaultActionGroup actionGroup) { actionGroup.addAction(new ShowModulesAction(myProject){ + @NotNull @Override protected String getId() { return PackageViewPane.this.getId(); diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java index e34cafbbb10c..3589918fe4a1 100644 --- a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java +++ b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java @@ -18,11 +18,9 @@ package com.intellij.javadoc; import com.intellij.CommonBundle; import com.intellij.analysis.AnalysisScope; import com.intellij.execution.ExecutionException; -import com.intellij.execution.Executor; -import com.intellij.execution.RunnerRegistry; import com.intellij.execution.executors.DefaultRunExecutor; -import com.intellij.execution.runners.ExecutionEnvironment; -import com.intellij.execution.runners.ProgramRunner; +import com.intellij.execution.runners.ExecutionEnvironmentBuilder; +import com.intellij.execution.runners.ExecutionUtil; import com.intellij.execution.util.ExecutionErrorDialog; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; @@ -82,10 +80,7 @@ public final class JavadocGenerationManager implements PersistentStateComponent< public void generateJavadoc(AnalysisScope scope) { myConfiguration.setGenerationScope(scope); try { - final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, myConfiguration); - assert runner != null; - Executor executor = DefaultRunExecutor.getRunExecutorInstance(); - runner.execute(new ExecutionEnvironment(myConfiguration ,executor, myProject, null)); + ExecutionEnvironmentBuilder.create(myProject, DefaultRunExecutor.getRunExecutorInstance(), myConfiguration).buildAndExecute(); } catch (ExecutionException e) { ExecutionErrorDialog.show(e, CommonBundle.getErrorTitle(), myProject); diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationPanel.java b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationPanel.java index 5cc096016683..d15ce5804170 100644 --- a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationPanel.java +++ b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -69,7 +69,7 @@ final class JavadocGenerationPanel extends JPanel { ); //noinspection UseOfObsoleteCollectionType - Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>(); + Hashtable<Integer, JComponent> labelTable = new Hashtable<Integer, JComponent>(); labelTable.put(new Integer(1), new JLabel(PsiKeyword.PUBLIC)); labelTable.put(new Integer(2), new JLabel(PsiKeyword.PROTECTED)); labelTable.put(new Integer(3), new JLabel(PsiKeyword.PACKAGE)); diff --git a/java/java-impl/src/com/intellij/psi/RefQueueIndex.java b/java/java-impl/src/com/intellij/psi/RefQueueIndex.java new file mode 100644 index 000000000000..d65fa4473c2f --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/RefQueueIndex.java @@ -0,0 +1,119 @@ +/* + * 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.psi; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.impl.file.impl.ResolveScopeManagerImpl; +import com.intellij.util.indexing.*; +import com.intellij.util.io.DataExternalizer; +import com.intellij.util.io.KeyDescriptor; +import org.jetbrains.annotations.NotNull; + +import java.io.DataInput; +import java.io.DataOutput; +import java.util.Collections; +import java.util.Map; + +// all it does is take files it was fed and queue them to the resolve +public class RefQueueIndex extends FileBasedIndexExtension<Void,Void> { + private static final ID<Void, Void> ID = com.intellij.util.indexing.ID.create("RefQueueIndex"); + + @NotNull + @Override + public ID<Void, Void> getName() { + return ID; + } + + @NotNull + @Override + public DataIndexer<Void, Void, FileContent> getIndexer() { + return new DataIndexer<Void, Void, FileContent>() { + @NotNull + @Override + public Map<Void, Void> map(@NotNull FileContent inputData) { + if (ResolveScopeManagerImpl.ENABLED_REF_BACK) { + Project project = inputData.getProject(); + RefResolveService.getInstance(project).queue(Collections.singletonList(inputData.getFile()), "Cache updater"); + } + return Collections.emptyMap(); + } + }; + } + + @NotNull + @Override + public KeyDescriptor<Void> getKeyDescriptor() { + return new KeyDescriptor<Void>() { + @Override + public void save(@NotNull DataOutput out, Void value) { + + } + + @Override + public Void read(@NotNull DataInput in) { + return null; + } + + @Override + public int getHashCode(Void value) { + return 0; + } + + @Override + public boolean isEqual(Void val1, Void val2) { + return false; + } + }; + } + + @NotNull + @Override + public DataExternalizer<Void> getValueExternalizer() { + return new DataExternalizer<Void>() { + @Override + public void save(@NotNull DataOutput out, Void value) { + + } + + @Override + public Void read(@NotNull DataInput in) { + return null; + } + }; + } + + @NotNull + @Override + public FileBasedIndex.InputFilter getInputFilter() { + return new FileBasedIndex.InputFilter() { + @Override + public boolean acceptInput(@NotNull VirtualFile file) { + return !file.isDirectory(); + } + }; + } + + @Override + public boolean dependsOnFileContent() { + return true; + } + + @Override + public int getVersion() { + return 0; + } +} diff --git a/java/java-impl/src/com/intellij/psi/RefResolveServiceImpl.java b/java/java-impl/src/com/intellij/psi/RefResolveServiceImpl.java new file mode 100644 index 000000000000..3655942f97b7 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/RefResolveServiceImpl.java @@ -0,0 +1,773 @@ +/* + * 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.psi; + +import com.intellij.concurrency.JobLauncher; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ApplicationAdapter; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.application.ex.ApplicationEx; +import com.intellij.openapi.application.ex.ApplicationUtil; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.progress.util.ProgressIndicatorUtils; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.project.IndexNotReadyException; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectCoreUtil; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.*; +import com.intellij.openapi.vfs.newvfs.BulkFileListener; +import com.intellij.openapi.vfs.newvfs.NewVirtualFile; +import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import com.intellij.openapi.vfs.newvfs.persistent.FSRecords; +import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS; +import com.intellij.psi.impl.PersistentIntList; +import com.intellij.psi.impl.file.impl.ResolveScopeManagerImpl; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiUtilCore; +import com.intellij.psi.xml.XmlElement; +import com.intellij.psi.xml.XmlFile; +import com.intellij.util.ArrayUtil; +import com.intellij.util.ExceptionUtil; +import com.intellij.util.Function; +import com.intellij.util.Processor; +import com.intellij.util.containers.ConcurrentBitSet; +import com.intellij.util.containers.ConcurrentIntObjectMap; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap; +import com.intellij.util.io.storage.HeavyProcessLatch; +import com.intellij.util.messages.MessageBus; +import gnu.trove.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.java.JavaSourceRootType; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.DateFormat; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +public class RefResolveServiceImpl extends RefResolveService implements Runnable, Disposable { + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.RefResolveService"); + private final AtomicInteger fileCount = new AtomicInteger(); + private final AtomicLong bytesSize = new AtomicLong(); + private final AtomicLong refCount = new AtomicLong(); + private final PersistentIntList storage; + private final Deque<VirtualFile> filesToResolve = new ArrayDeque<VirtualFile>(); + private final ConcurrentBitSet fileIsInQueue = new ConcurrentBitSet(); + private final ConcurrentBitSet fileIsResolved; + private final ApplicationEx myApplication; + private volatile boolean myDisposed; + private volatile boolean upToDate; + private volatile boolean enabled = true; + private final FileWriter log; + private final ProjectFileIndex myProjectFileIndex; + + + public RefResolveServiceImpl(final Project project, + final MessageBus messageBus, + final PsiManager psiManager, + StartupManager startupManager, + ApplicationEx application, + ProjectFileIndex projectFileIndex) throws IOException { + super(project); + myApplication = application; + myProjectFileIndex = projectFileIndex; + if (ResolveScopeManagerImpl.ENABLED_REF_BACK) { + File indexFile = new File(getStorageDirectory(), "index"); + File dataFile = new File(getStorageDirectory(), "data"); + fileIsResolved = ConcurrentBitSet.readFrom(new File(getStorageDirectory(), "bitSet")); + + final boolean initial = !indexFile.exists() || !dataFile.exists(); + storage = new PersistentIntList(indexFile, dataFile, initial); + Disposer.register(this, storage); + if (!application.isUnitTestMode()) { + startupManager.runWhenProjectIsInitialized(new Runnable() { + @Override + public void run() { + init(messageBus, psiManager); + } + }); + } + log = new FileWriter(new File(getStorageDirectory(), "log.txt")); + Disposer.register(this, new Disposable() { + @Override + public void dispose() { + try { + save(); + log.close(); + } + catch (IOException e) { + LOG.error(e); + } + } + }); + } + else { + log = null; + fileIsResolved = null; + storage = null; + } + } + + public static List<VirtualFile> toVf(@NotNull int[] ids) { + List<VirtualFile> res = new ArrayList<VirtualFile>(); + for (int id : ids) { + VirtualFile file = PersistentFS.getInstance().findFileById(id); + if (file != null) { + res.add(file); + } + } + return res; + } + + public static String toVfString(@NotNull int[] backIds) { + List<VirtualFile> list = toVf(backIds); + return toVfString(list); + } + + private static String toVfString(@NotNull List<VirtualFile> list) { + List<VirtualFile> sub = list.subList(0, Math.min(list.size(), 100)); + return list.size() + " files: " + StringUtil.join(sub, new Function<VirtualFile, String>() { + @Override + public String fun(VirtualFile file) { + return file.getName(); + } + }, ", ")+(list.size()==sub.size() ? "" : "..."); + } + + private void init(@NotNull MessageBus messageBus, @NotNull PsiManager psiManager) { + messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter(){ + @Override + public void after(@NotNull List<? extends VFileEvent> events) { + fileCount.set(0); + List<VirtualFile> files = ContainerUtil.mapNotNull(events, new Function<VFileEvent, VirtualFile>() { + @Override + public VirtualFile fun(VFileEvent event) { + return event.getFile(); + } + }); + queue(files, "VFS events " + events.size()); + } + }); + psiManager.addPsiTreeChangeListener(new PsiTreeChangeAdapter() { + @Override + public void childrenChanged(@NotNull PsiTreeChangeEvent event) { + PsiFile file = event.getFile(); + VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file); + if (virtualFile != null) { + queue(Collections.singletonList(virtualFile), event); + } + } + + @Override + public void propertyChanged(@NotNull PsiTreeChangeEvent event) { + childrenChanged(event); + } + }); + + messageBus.connect().subscribe(DumbService.DUMB_MODE, new DumbService.DumbModeListener() { + @Override + public void enteredDumbMode() { + disable(); + } + + @Override + public void exitDumbMode() { + enable(); + } + }); + myApplication.addApplicationListener(new ApplicationAdapter() { + @Override + public void beforeWriteActionStart(Object action) { + disable(); + } + + @Override + public void writeActionFinished(Object action) { + enable(); + } + + @Override + public void applicationExiting() { + disable(); + } + }, this); + VirtualFileManager.getInstance().addVirtualFileManagerListener(new VirtualFileManagerListener() { + @Override + public void beforeRefreshStart(boolean asynchronous) { + disable(); + } + + @Override + public void afterRefreshFinish(boolean asynchronous) { + enable(); + } + }, this); + Disposer.register(this, HeavyProcessLatch.INSTANCE.addListener(new HeavyProcessLatch.HeavyProcessListener() { + @Override + public void processStarted() { + disable(); + } + + @Override + public void processFinished() { + enable(); + } + })); + + startThread(); + } + + // return true if file was added to queue + private boolean queueIfNeeded(VirtualFile virtualFile, @NotNull Project project) { + return toResolve(virtualFile, project) && queueUpdate(virtualFile); + } + + private boolean toResolve(VirtualFile virtualFile, @NotNull Project project) { + if (virtualFile != null && + virtualFile.isValid() && + project.isInitialized() && + myProjectFileIndex.isInContent(virtualFile)) { + if (virtualFile.isDirectory()) return true; + if (virtualFile.getFileType() == StdFileTypes.JAVA) return true; + if (virtualFile.getFileType() == StdFileTypes.XML && !ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile)) return true; + } + + // else mark it as resolved so we will not have to check it again + if (virtualFile instanceof VirtualFileWithId) { + int id = getAbsId(virtualFile); + fileIsResolved.set(id); + } + + return false; + } + + @NotNull + private File getStorageDirectory() { + String dirName = myProject.getName() + "."+Integer.toHexString(myProject.getPresentableUrl().hashCode()); + File dir = new File(PathManager.getSystemPath(), "refs/" + dirName); + FileUtil.createDirectory(dir); + return dir; + } + + + private void log(String m) { + //System.out.println(m); + logf(m); + } + + private void logf(String m) { + try { + log.write(DateFormat.getDateTimeInstance().format(new Date()) + " "+m+" ; gap="+storage.gap+"\n"); + } + catch (IOException e) { + LOG.error(e); + } + } + + private void flushLog() { + try { + log.flush(); + } + catch (IOException e) { + LOG.error(e); + } + } + + // return true if file was added to queue + private boolean queueUpdate(@NotNull VirtualFile file) { + synchronized (filesToResolve) { + if (!(file instanceof VirtualFileWithId)) return false; + int fileId = getAbsId(file); + countAndMarkUnresolved(file, new THashSet<VirtualFile>(), true); + boolean alreadyAdded = fileIsInQueue.set(fileId); + if (!alreadyAdded) { + filesToResolve.add(file); + } + upToDate = false; + wakeUpUnderLock(); + return !alreadyAdded; + } + } + + private void wakeUp() { + synchronized (filesToResolve) { + wakeUpUnderLock(); + } + } + + private void wakeUpUnderLock() { + filesToResolve.notifyAll(); + } + + private void waitForQueue() throws InterruptedException { + synchronized (filesToResolve) { + filesToResolve.wait(1000); + } + } + + private void startThread() { + new Thread(this, "Ref resolve service").start(); + upToDate = true; + queueUnresolvedFilesSinceLastRestart(); + } + + private void queueUnresolvedFilesSinceLastRestart() { + PersistentFS fs = PersistentFS.getInstance(); + int maxId = FSRecords.getMaxId(); + TIntArrayList list = new TIntArrayList(); + for (int id= fileIsResolved.nextClearBit(1); id >= 0 && id < maxId; id = fileIsResolved.nextClearBit(id + 1)) { + int nextSetBit = fileIsResolved.nextSetBit(id); + int endOfRun = Math.min(maxId, nextSetBit == -1 ? maxId : nextSetBit); + do { + VirtualFile virtualFile = fs.findFileById(id); + if (queueIfNeeded(virtualFile, myProject)) { + list.add(id); + } + } + while (++id < endOfRun); + } + log("Initially added to resolve " + toVfString(list.toNativeArray())); + } + + @Override + public void dispose() { + myDisposed = true; + } + + private void save() throws IOException { + fileIsResolved.writeTo(new File(getStorageDirectory(), "bitSet")); + } + + @Override + public void run() { + while (!myDisposed) { + boolean isEmpty; + synchronized (filesToResolve) { + isEmpty = filesToResolve.isEmpty(); + } + if (!enabled || isEmpty) { + try { + waitForQueue(); + } + catch (InterruptedException e) { + break; + } + continue; + } + upToDate = false; + final CountDownLatch batchProcessedLatch = new CountDownLatch(1); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + new Task.Backgroundable(myProject, "Resolving files...", true) { + @Override + public void run(@NotNull final ProgressIndicator indicator) { + if (ApplicationManager.getApplication().isDisposed()) return; + try { + processBatch(indicator); + } + finally { + batchProcessedLatch.countDown(); + } + } + }.queue(); + } + }, myProject.getDisposed()); + + try { + batchProcessedLatch.await(); + } + catch (InterruptedException e) { + break; + } + + synchronized (filesToResolve) { + upToDate = filesToResolve.isEmpty(); + log("upToDate = " + upToDate); + } + flushLog(); + } + } + + private void processBatch(@NotNull final ProgressIndicator indicator) { + Set<VirtualFile> set; + int queuedSize; + synchronized (filesToResolve) { + queuedSize = filesToResolve.size(); + set = new THashSet<VirtualFile>(queuedSize); + // someone might have cleared this bit to mark file as processed + for (VirtualFile file : filesToResolve) { + if (fileIsInQueue.clear(getAbsId(file))) { + set.add(file); + } + } + filesToResolve.clear(); + } + final ConcurrentIntObjectMap<int[]> fileToForwardIds = new StripedLockIntObjectConcurrentHashMap<int[]>(); + Set<VirtualFile> files = countAndMarkUnresolved(set, false); + if (files.isEmpty()) return; + final int size = files.size(); + final Set<VirtualFile> toProcess = Collections.synchronizedSet(files); + log("Started to resolve "+ size + " files (was queued "+queuedSize+")"); + + indicator.setIndeterminate(false); + ProgressIndicatorUtils.forceWriteActionPriority(indicator, (Disposable)indicator); + long start = System.currentTimeMillis(); + Processor<VirtualFile> processor = new Processor<VirtualFile>() { + @Override + public boolean process(VirtualFile file) { + double fraction = 1 - toProcess.size() * 1.0 / size; + indicator.setFraction(fraction); + try { + if (file.isDirectory() || !toResolve(file, myProject)) { + return true; + } + int fileId = getAbsId(file); + int i = size - toProcess.size(); + indicator.setText(i + "/" + size + ": Resolving " + file.getPresentableUrl()); + int[] forwardIds = processFile(file, fileId, indicator); + if (forwardIds == null) { + //queueUpdate(file); + return false; + } + toProcess.remove(file); + fileToForwardIds.put(fileId, forwardIds); + } + catch (RuntimeException e) { + indicator.checkCanceled(); + } + return true; + } + }; + boolean success = true; + try { + success = JobLauncher + .getInstance().invokeConcurrentlyUnderProgress(new ArrayList<VirtualFile>(files), indicator, false, false, processor); + } + finally { + queue(toProcess, "re-added after fail. success=" + success); + storeIds(fileToForwardIds); + + long end = System.currentTimeMillis(); + log("Resolved batch of " + (size - toProcess.size()) + " from " + size + " files in " + ((end - start) / 1000) + "sec. (Gap: " + storage.gap+")"); + } + } + + private static int getAbsId(@NotNull VirtualFile file) { + return Math.abs(((VirtualFileWithId)file).getId()); + } + + @NotNull + private Set<VirtualFile> countAndMarkUnresolved(@NotNull Collection<VirtualFile> files, boolean inDbOnly) { + Set<VirtualFile> result = new THashSet<VirtualFile>(); + for (VirtualFile file : files) { + countAndMarkUnresolved(file, result, inDbOnly); + } + return result; + } + + private void countAndMarkUnresolved(@NotNull VirtualFile file, @NotNull final Set<VirtualFile> result, final boolean inDbOnly) { + if (file.isDirectory()) { + VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() { + @Override + public boolean visitFile(@NotNull VirtualFile file) { + doCountAndMarkUnresolved(file, result); + return true; + } + + @Nullable + @Override + public Iterable<VirtualFile> getChildrenIterable(@NotNull VirtualFile file) { + return inDbOnly ? ((NewVirtualFile)file).iterInDbChildren() : null; + } + }); + } + else { + doCountAndMarkUnresolved(file, result); + } + } + + private void doCountAndMarkUnresolved(@NotNull VirtualFile file, @NotNull Set<VirtualFile> result) { + if (file.isDirectory()) { + fileIsResolved.set(getAbsId(file)); + } + else if (toResolve(file, myProject)) { + result.add(file); + fileIsResolved.clear(getAbsId(file)); + } + } + + private void enable() { + enabled = true; + wakeUp(); + } + + private void disable() { + enabled = false; + wakeUp(); + } + + // returns list of resolved files if updated successfully, or null if write action or dumb mode started + private int[] processFile(@NotNull final VirtualFile file, + int fileId, + @NotNull final ProgressIndicator indicator) { + final TIntHashSet forward; + try { + forward = calcForwardRefs(file, indicator); + } + catch (IndexNotReadyException e) { + return null; + } + catch (ApplicationUtil.CannotRunReadActionException e) { + return null; + } + catch (ProcessCanceledException e) { + throw e; + } + catch (Exception e) { + log(ExceptionUtil.getThrowableText(e)); + flushLog(); + return null; + } + + int[] forwardIds = forward.toArray(); + fileIsResolved.set(fileId); + logf(" ---- "+file.getPresentableUrl() + " processed. forwardIds: "+ toVfString(forwardIds)); + return forwardIds; + } + + private void storeIds(@NotNull ConcurrentIntObjectMap<int[]> fileToForwardIds) { + int forwardSize = 0; + int backwardSize = 0; + final TIntObjectHashMap<TIntArrayList> fileToBackwardIds = new TIntObjectHashMap<TIntArrayList>(fileToForwardIds.size()); + for (StripedLockIntObjectConcurrentHashMap.IntEntry<int[]> entry : fileToForwardIds.entries()) { + int fileId = entry.getKey(); + int[] forwardIds = entry.getValue(); + forwardSize += forwardIds.length; + for (int forwardId : forwardIds) { + TIntArrayList backIds = fileToBackwardIds.get(forwardId); + if (backIds == null) { + backIds = new TIntArrayList(); + fileToBackwardIds.put(forwardId, backIds); + } + backIds.add(fileId); + backwardSize++; + } + } + log("backwardSize = " + backwardSize); + log("forwardSize = " + forwardSize); + log("fileToForwardIds.size() = "+fileToForwardIds.size()); + log("fileToBackwardIds.size() = "+fileToBackwardIds.size()); + assert forwardSize == backwardSize; + + // wrap in read action so that sudden quit (in write action) would not interrupt us + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + fileToBackwardIds.forEachEntry(new TIntObjectProcedure<TIntArrayList>() { + @Override + public boolean execute(int fileId, TIntArrayList backIds) { + storage.addAll(fileId, backIds.toNativeArray()); + return true; + } + }); + } + }); + } + + + @NotNull + private TIntHashSet calcForwardRefs(@NotNull final VirtualFile virtualFile, @NotNull final ProgressIndicator indicator) + throws IndexNotReadyException, ApplicationUtil.CannotRunReadActionException { + if (myProject.isDisposed()) throw new ProcessCanceledException(); + if (fileCount.incrementAndGet() % 100 == 0) { + PsiManager.getInstance(myProject).dropResolveCaches(); + synchronized (storage) { + storage.flush(); + } + try { + log.flush(); + } + catch (IOException e) { + LOG.error(e); + } + } + + final TIntHashSet forward = new TIntHashSet(); + + final PsiFile psiFile = ApplicationUtil.tryRunReadAction(new Computable<PsiFile>() { + @Override + public PsiFile compute() { + return PsiManager.getInstance(myProject).findFile(virtualFile); + } + }); + final int fileId = getAbsId(virtualFile); + if (psiFile != null) { + bytesSize.addAndGet(virtualFile.getLength()); + final Set<PsiElement> resolved = new THashSet<PsiElement>(); + ApplicationUtil.tryRunReadAction(new Runnable() { + @Override + public void run() { + indicator.checkCanceled(); + + if (psiFile instanceof PsiJavaFile) { + psiFile.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { + resolveReference(reference, indicator, resolved); + + super.visitReferenceElement(reference); + } + }); + } + else if (psiFile instanceof XmlFile) { + psiFile.accept(new XmlRecursiveElementWalkingVisitor() { + @Override + public void visitXmlElement(XmlElement element) { + for (PsiReference reference : element.getReferences()) { + resolveReference(reference, indicator, resolved); + } + super.visitXmlElement(element); + } + }); + } + + indicator.checkCanceled(); + for (PsiElement element : resolved) { + PsiFile file = element.getContainingFile(); + addIdAndSuperClasses(file, forward); + } + } + }); + } + + forward.remove(fileId); + return forward; + } + + private void resolveReference(@NotNull PsiReference reference, @NotNull ProgressIndicator indicator, @NotNull Set<PsiElement> resolved) { + indicator.checkCanceled(); + PsiElement element = reference.resolve(); + if (element != null) { + resolved.add(element); + } + refCount.incrementAndGet(); + } + + private static void addIdAndSuperClasses(PsiFile file, @NotNull TIntHashSet forward) { + if (file instanceof PsiJavaFile && file.getName().equals("Object.class") && ((PsiJavaFile)file).getPackageName().equals("java.lang")) { + return; + } + VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file); + if (virtualFile instanceof VirtualFileWithId && forward.add(getAbsId(virtualFile)) && file instanceof PsiClassOwner) { + for (PsiClass aClass : ((PsiClassOwner)file).getClasses()) { + for (PsiClass superClass : aClass.getSupers()) { + addIdAndSuperClasses(superClass.getContainingFile(), forward); + } + } + } + } + + @Override + @Nullable + public int[] getBackwardIds(@NotNull VirtualFileWithId file) { + if (!upToDate) return null; + int fileId = getAbsId((VirtualFile)file); + return storage.get(fileId); + } + + private String prevLog = ""; + private static final Set<JavaSourceRootType> SOURCE_ROOTS = ContainerUtil.newTroveSet(JavaSourceRootType.SOURCE, JavaSourceRootType.TEST_SOURCE); + + @NotNull + @Override + public GlobalSearchScope restrictByBackwardIds(@NotNull final VirtualFile virtualFile, @NotNull GlobalSearchScope scope) { + final int[] backIds = RefResolveService.getInstance(myProject).getBackwardIds((VirtualFileWithId)virtualFile); + if (backIds == null) { + return scope; + } + String files = toVfString(backIds); + String log = "Restricting scope of " + virtualFile.getName() + " to " + files; + if (!log.equals(prevLog)) { + log(log); + flushLog(); + prevLog = log; + } + GlobalSearchScope restrictedByBackwardIds = new GlobalSearchScope() { + @Override + public boolean contains(@NotNull VirtualFile file) { + if (!(file instanceof VirtualFileWithId) + || file.equals(virtualFile) + || ArrayUtil.indexOf(backIds, getAbsId(file)) != -1) return true; + return false & !myProjectFileIndex.isUnderSourceRootOfType(file, SOURCE_ROOTS); // filter out source file which we know for sure does not reference the element + } + + @Override + public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) { + return 0; + } + + @Override + public boolean isSearchInModuleContent(@NotNull Module aModule) { + return true; + } + + @Override + public boolean isSearchInLibraries() { + return false; + } + }; + return scope.intersectWith(restrictedByBackwardIds); + } + + @Override + public boolean queue(@NotNull Collection<VirtualFile> files, Object reason) { + if (files.isEmpty()) { + return false; + } + boolean queued = false; + List<VirtualFile> added = new ArrayList<VirtualFile>(files.size()); + for (VirtualFile file : files) { + boolean wasAdded = queueIfNeeded(file, myProject); + if (wasAdded) { + added.add(file); + } + queued |= wasAdded; + } + if (queued) { + log("Queued to resolve (from " + reason + "): " + toVfString(added)); + flushLog(); + } + return queued; + } +} diff --git a/java/java-impl/src/com/intellij/psi/filters/FilterUtil.java b/java/java-impl/src/com/intellij/psi/filters/FilterUtil.java index 89033fae439f..061e0bf18916 100644 --- a/java/java-impl/src/com/intellij/psi/filters/FilterUtil.java +++ b/java/java-impl/src/com/intellij/psi/filters/FilterUtil.java @@ -40,6 +40,12 @@ public class FilterUtil{ return JavaPsiFacade.getInstance(element.getProject()).getElementFactory().createType((PsiClass)element); } if(element instanceof PsiMethod){ + if (((PsiMethod)element).isConstructor()) { + final PsiClass containingClass = ((PsiMethod)element).getContainingClass(); + if (containingClass != null) { + return JavaPsiFacade.getInstance(element.getProject()).getElementFactory().createType(containingClass); + } + } return ((PsiMethod)element).getReturnType(); } if(element instanceof PsiVariable){ 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 28748028c246..4d225e65d88b 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 @@ -222,13 +222,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { return; } if (myRole2 == ChildRole.LBRACE) { - PsiIdentifier nameIdentifier = aClass.getNameIdentifier(); - int dependanceStart = nameIdentifier == null ? myParent.getTextRange().getStartOffset() : nameIdentifier.getTextRange().getStartOffset(); - ASTNode next = FormatterUtil.getNextNonWhitespaceSibling(myChild2); - boolean keepOneLine = mySettings.KEEP_SIMPLE_CLASSES_IN_ONE_LINE && next != null && next.getElementType() == JavaTokenType.RBRACE; - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_CLASS_LBRACE, mySettings.CLASS_BRACE_STYLE, - new TextRange(dependanceStart, myChild1.getTextRange().getEndOffset()), - keepOneLine, true); + myResult = getSpaceBeforeClassLBrace(aClass); } else if (myRole1 == ChildRole.LBRACE || isEndOfLineCommentAfterLBrace(myChild1)) { if (aClass.isEnum()) { @@ -276,10 +270,131 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { } } - private boolean isEndOfLineCommentAfterLBrace(@NotNull ASTNode node) { + @NotNull + private Spacing getSpaceBeforeMethodLBrace(@NotNull PsiMethod method) { + final int space = mySettings.SPACE_BEFORE_METHOD_LBRACE ? 1 : 0; + final int methodBraceStyle = mySettings.METHOD_BRACE_STYLE; + + if (methodBraceStyle == CommonCodeStyleSettings.END_OF_LINE) { + return createNonLFSpace(space, null, false); + } + else if (methodBraceStyle == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED) { + TextRange headerRange = new TextRange(getMethodHeaderStartOffset(method), getMethodHeaderEndOffset(method)); + return createNonLFSpace(space, headerRange, false); + } + else if (shouldHandleAsSimpleMethod(method)) { + TextRange rangeWithoutAnnotations = new TextRange(getMethodHeaderStartOffset(method), method.getTextRange().getEndOffset()); + return createNonLFSpace(space, rangeWithoutAnnotations, false); + } + + return Spacing.createSpacing(space, space, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE); + } + + private static int getMethodHeaderEndOffset(@NotNull PsiMethod method) { + PsiElement headerEnd = method.getBody() != null ? method.getBody().getPrevSibling() : null; + if (headerEnd != null) { + return headerEnd.getTextRange().getEndOffset(); + } + return method.getTextRange().getEndOffset(); + } + + @NotNull + private Spacing getSpaceBeforeClassLBrace(@NotNull PsiClass aClass) { + final int space = mySettings.SPACE_BEFORE_CLASS_LBRACE ? 1 : 0; + final int classBraceStyle = mySettings.CLASS_BRACE_STYLE; + + if (classBraceStyle == CommonCodeStyleSettings.END_OF_LINE || shouldHandleAsSimpleClass(aClass)) { + return createNonLFSpace(space, null, false); + } + else if (classBraceStyle == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED) { + final PsiIdentifier nameIdentifier = aClass.getNameIdentifier(); + final int startOffset = nameIdentifier == null ? myParent.getTextRange().getStartOffset() : nameIdentifier.getTextRange().getStartOffset(); + TextRange range = new TextRange(startOffset, myChild1.getTextRange().getEndOffset()); + return createNonLFSpace(space, range, false); + } + + return Spacing.createSpacing(space, space, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE); + } + + private Spacing getSpaceBeforeLBrace(@NotNull ASTNode lBraceBlock, boolean spaceBeforeLbrace, @Nullable TextRange nextLineIfWrappedOptionRange) { + int space = spaceBeforeLbrace ? 1 : 0; + + if (mySettings.BRACE_STYLE == CommonCodeStyleSettings.END_OF_LINE) { + return createNonLFSpace(space, null, false); + } + else if (mySettings.BRACE_STYLE == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED) { + return createNonLFSpace(space, nextLineIfWrappedOptionRange, false); + } + else if (shouldHandleAsSimpleBlock(lBraceBlock)) { + return createNonLFSpace(space, lBraceBlock.getTextRange(), false); + } + + return Spacing.createSpacing(space, space, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE); + } + + private boolean shouldHandleAsSimpleClass(@NotNull PsiClass aClass) { + if (!mySettings.KEEP_SIMPLE_CLASSES_IN_ONE_LINE) return false; + + final PsiElement lBrace = aClass.getLBrace(); + final PsiElement rBrace = aClass.getRBrace(); + if (lBrace != null && rBrace != null) { + PsiElement beforeLBrace = lBrace.getPrevSibling(); + if (beforeLBrace instanceof PsiWhiteSpace && beforeLBrace.textContains('\n')) { + return false; + } + + PsiElement betweenBraces = lBrace.getNextSibling(); + if (betweenBraces == rBrace || isWhiteSpaceWithoutLinefeeds(betweenBraces) && betweenBraces.getNextSibling() == rBrace) { + return true; + } + } + + return false; + } + + private static boolean isWhiteSpaceWithoutLinefeeds(@Nullable PsiElement betweenBraces) { + return betweenBraces instanceof PsiWhiteSpace && !betweenBraces.textContains('\n'); + } + + private boolean shouldHandleAsSimpleBlock(@NotNull ASTNode node) { + if (!mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) return false; + + PsiElement prev = node.getPsi().getPrevSibling(); + if (prev instanceof PsiWhiteSpace && prev.textContains('\n')) { + return false; + } + return !node.textContains('\n'); + } + + private boolean shouldHandleAsSimpleMethod(@NotNull PsiMethod method) { + if (!mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE) return false; + + boolean skipElement = true; + for (PsiElement element : method.getChildren()) { + if (element instanceof PsiTypeElement) skipElement = false; + if (skipElement) continue; + + if (element.textContains('\n')) { + return false; + } + } + + return true; + } + + private static int getMethodHeaderStartOffset(@NotNull PsiMethod method) { + for (PsiElement element : method.getChildren()) { + if (element instanceof PsiTypeElement) { + return element.getTextRange().getStartOffset(); + } + } + return method.getTextRange().getStartOffset(); + } + + private static boolean isEndOfLineCommentAfterLBrace(@NotNull ASTNode node) { if (node.getPsi() instanceof PsiComment) { PsiElement ws = node.getPsi().getPrevSibling(); - if (ws instanceof PsiWhiteSpace && !ws.textContains('\n')) { + if (isWhiteSpaceWithoutLinefeeds(ws)) { PsiElement beforeWs = ws.getPrevSibling(); if (beforeWs instanceof PsiJavaToken && ((PsiJavaToken)beforeWs).getTokenType() == JavaTokenType.LBRACE) { return true; @@ -580,14 +695,11 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { } else if (myRole2 == ChildRole.LOOP_BODY || myChild2.getElementType() == JavaElementType.CODE_BLOCK) { if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT) { - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_WHILE_LBRACE, mySettings.BRACE_STYLE, - new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()), - mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true); + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_WHILE_LBRACE, null); } else { createSpacingBeforeElementInsideControlStatement(); } } - } @Override @@ -600,8 +712,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { } else if (myRole2 == ChildRole.LOOP_BODY) { if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT) { - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_DO_LBRACE, mySettings.BRACE_STYLE, null, - mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true); + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_DO_LBRACE, null); } else { createSpacingBeforeElementInsideControlStatement(); } @@ -652,25 +763,16 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { } if (myRole2 == ChildRole.TRY_BLOCK) { - TextRange dependantRange = getDependencyRangeForLBraceWhiteSpace(statement.getTryBlock()); - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_TRY_LBRACE, mySettings.BRACE_STYLE, dependantRange, mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, false); + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_TRY_LBRACE, null); } else if (myRole2 == ChildRole.FINALLY_BLOCK) { - TextRange dependantRange = getDependencyRangeForLBraceWhiteSpace(statement.getFinallyBlock()); - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_FINALLY_LBRACE, mySettings.BRACE_STYLE, dependantRange, mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, false); + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_FINALLY_LBRACE, null); } else if (myType2 == JavaElementType.RESOURCE_LIST) { createSpaceInCode(mySettings.SPACE_BEFORE_TRY_PARENTHESES); } } - @Nullable - private TextRange getDependencyRangeForLBraceWhiteSpace(PsiElement element) { - return mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE && element != null - ? element.getTextRange() - : null; - } - @Override public void visitForeachStatement(PsiForeachStatement statement) { if (myRole1 == ChildRole.FOR_KEYWORD && myRole2 == ChildRole.LPARENTH) { @@ -686,9 +788,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { } else if (myRole2 == ChildRole.LOOP_BODY) { if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT) { - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_FOR_LBRACE, mySettings.BRACE_STYLE, - new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()), - mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true); + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_FOR_LBRACE, null); } else if (mySettings.KEEP_CONTROL_STATEMENT_IN_ONE_LINE) { myResult = Spacing.createDependentLFSpacing(1, 1, myParent.getTextRange(), false, mySettings.KEEP_BLANK_LINES_IN_CODE); @@ -782,8 +882,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { else if (myChild1.getElementType() == JavaElementType.SWITCH_LABEL_STATEMENT && myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT) { - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_SWITCH_LBRACE, mySettings.BRACE_STYLE, null, false, true); - + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_SWITCH_LBRACE, null); } else if (lhsStatement && rhsStatement) { int minSpaces = 0; @@ -813,11 +912,11 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { private boolean keepInOneLine(final PsiCodeBlock block) { if (block.getParent() instanceof PsiMethod) { - return mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE; + return shouldHandleAsSimpleMethod((PsiMethod)block.getParent()); } else { - return mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE; - } + return shouldHandleAsSimpleBlock(block.getNode()); + } } @Override @@ -846,10 +945,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { } else { if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT || myChild2.getElementType() == JavaElementType.CODE_BLOCK) { - TextRange dependantRange = getDependencyRangeForLBraceWhiteSpace(statement.getElseBranch()); - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_ELSE_LBRACE, - mySettings.BRACE_STYLE, - dependantRange, mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, false); + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_ELSE_LBRACE, null); } else { createSpacingBeforeElementInsideControlStatement(); @@ -859,17 +955,13 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { else if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT || myChild2.getElementType() == JavaElementType.CODE_BLOCK) { boolean space = myRole2 == ChildRole.ELSE_BRANCH ? mySettings.SPACE_BEFORE_ELSE_LBRACE : mySettings.SPACE_BEFORE_IF_LBRACE; - - PsiElement branch = myRole2 == ChildRole.ELSE_BRANCH ? statement.getElseBranch() - : statement.getThenBranch(); - - TextRange dependantRange = mySettings.BRACE_STYLE == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED || branch == null - ? new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()) - : branch.getTextRange(); - - myResult = getSpaceBeforeLBrace(space, mySettings.BRACE_STYLE, - dependantRange, - mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, false); + + TextRange dependentRange = null; + if (myRole2 == ChildRole.THEN_BRANCH) { + PsiExpression condition = statement.getCondition(); + if (condition != null) dependentRange = condition.getTextRange(); + } + myResult = getSpaceBeforeLBrace(myChild2, space, dependentRange); } else if (myRole2 == ChildRole.LPARENTH) { createSpaceInCode(mySettings.SPACE_BEFORE_IF_PARENTHESES); @@ -911,29 +1003,6 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { return FormatterUtil.getPreviousNonWhitespaceLeaf(child); } - private Spacing getSpaceBeforeLBrace(final boolean spaceBeforeLbrace, - @CommonCodeStyleSettings.BraceStyleConstant int braceStyle, - @Nullable TextRange dependantRange, - boolean keepOneLine, - boolean useParentBlockAsDependencyAllTheTime) - { - int space = spaceBeforeLbrace ? 1 : 0; - if (dependantRange != null && braceStyle == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED) { - return createNonLFSpace(space, dependantRange, false); - } - else if (braceStyle == CommonCodeStyleSettings.END_OF_LINE || braceStyle == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED) { - return createNonLFSpace(space, null, false); - } - else if (keepOneLine) { - TextRange dependencyRangeToUse = dependantRange == null || useParentBlockAsDependencyAllTheTime - ? myParent.getTextRange() : dependantRange; - - return Spacing.createDependentLFSpacing(space, space, dependencyRangeToUse, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - else { - return Spacing.createSpacing(0, 0, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE); - } - } @Override public void visitPolyadicExpression(PsiPolyadicExpression expression) { @@ -1029,37 +1098,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { createSpaceInCode(true); } else if (myRole2 == ChildRole.METHOD_BODY) { - PsiElement methodName = method.getNameIdentifier(); - int dependencyStart = methodName == null ? myParent.getTextRange().getStartOffset() : methodName.getTextRange().getStartOffset(); - PsiModifierList modifierList = method.getModifierList(); - PsiAnnotation[] annotations = modifierList.getAnnotations(); - boolean useParentBlockAsDependencyAllTheTime = true; - if (annotations.length > 0) { - useParentBlockAsDependencyAllTheTime = false; - PsiAnnotation annotation = annotations[annotations.length - 1]; - ASTNode nextModifier = FormatterUtil.getNextNonWhitespaceSibling(annotation.getNode()); - if (nextModifier == null) { - PsiElement element = modifierList.getNextSibling(); - if (element != null) { - ASTNode node = element.getNode(); - if (node != null && node.getTextLength() > 0) { - dependencyStart = element.getTextRange().getStartOffset(); - } - } - } else { - dependencyStart = nextModifier.getStartOffset(); - } - } - - ASTNode dependencyEndAnchor = mySettings.METHOD_BRACE_STYLE == CommonCodeStyleSettings.NEXT_LINE ? myChild2 : myChild1; - int dependencyEnd = dependencyEndAnchor.getTextRange().getEndOffset(); - boolean keepInOneLine = mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE - && method.getBody() != null - && !method.getBody().textContains('\n'); - - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.METHOD_BRACE_STYLE, - new TextRange(dependencyStart, dependencyEnd), keepInOneLine, - useParentBlockAsDependencyAllTheTime); + myResult = getSpaceBeforeMethodLBrace(method); } else if (myRole1 == ChildRole.MODIFIER_LIST) { processModifierList(); @@ -1176,8 +1215,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { createSpaceInCode(mySettings.SPACE_WITHIN_SYNCHRONIZED_PARENTHESES); } else if (myRole2 == ChildRole.BLOCK) { - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_SYNCHRONIZED_LBRACE, mySettings.BRACE_STYLE, null, - mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true); + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_SYNCHRONIZED_LBRACE, null); } } @@ -1197,10 +1235,8 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { createSpaceInCode(mySettings.SPACE_WITHIN_SWITCH_PARENTHESES); } else if (myRole2 == ChildRole.SWITCH_BODY) { - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_SWITCH_LBRACE, mySettings.BRACE_STYLE, null, - mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true); + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_SWITCH_LBRACE, null); } - } @Override @@ -1265,9 +1301,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { } else if (myRole2 == ChildRole.LOOP_BODY || myChild2.getElementType() == JavaElementType.CODE_BLOCK) { if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT) { - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_FOR_LBRACE, mySettings.BRACE_STYLE, - new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()), - mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true); + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_FOR_LBRACE, null); } else if (mySettings.KEEP_CONTROL_STATEMENT_IN_ONE_LINE) { myResult = Spacing.createDependentLFSpacing(1, 1, myParent.getTextRange(), false, mySettings.KEEP_BLANK_LINES_IN_CODE); @@ -1290,9 +1324,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { @Override public void visitCatchSection(PsiCatchSection section) { if (myRole2 == ChildRole.CATCH_BLOCK) { - TextRange dependantRange = mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE ? section.getTextRange() : null; - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_CATCH_LBRACE, mySettings.BRACE_STYLE, dependantRange, - mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true); + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_CATCH_LBRACE, null); } else if (myRole2 == ChildRole.CATCH_BLOCK_PARAMETER_LPARENTH) { createSpaceInCode(mySettings.SPACE_BEFORE_CATCH_PARENTHESES); @@ -1512,7 +1544,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { @Override public void visitClassInitializer(PsiClassInitializer initializer) { if (myChild2.getElementType() == JavaElementType.CODE_BLOCK) { - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.BRACE_STYLE, null, false, true); + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_METHOD_LBRACE, null); } } @@ -1588,8 +1620,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { createSpaceInCode(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES); } else if (myRole2 == ChildRole.ANONYMOUS_CLASS) { - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_CLASS_LBRACE, mySettings.METHOD_BRACE_STYLE, enumConstant.getTextRange(), - mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE, true); + myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_CLASS_LBRACE, null); } } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java index a35b6e36e756..d7028b99fcff 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java @@ -1064,7 +1064,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager { public static boolean isStringPsiLiteral(PsiElement element) { if (element instanceof PsiLiteralExpression) { final String text = element.getText(); - return text.length() > 1 && StringUtil.isQuotedString(text); + return StringUtil.isQuotedString(text); } return false; } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java index 13644930d88e..776f68bd2cfe 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java @@ -26,6 +26,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.impl.source.PsiClassReferenceType; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.*; +import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -44,6 +45,11 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp } @Override + public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException { + return element; + } + + @Override public PsiElement resolve() { final String name = (String)getElement().getValue(); final Type type = getType(); diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java index b551616c93dc..49064514be38 100644 --- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java @@ -332,7 +332,7 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase { for (final PsiClass[] psiClasses : fileToClasses.values()) { if (psiClasses != null) { for (PsiClass aClass : psiClasses) { - if (aClass instanceof SyntheticElement) { + if (isSynthetic(aClass)) { continue; } oldToNewMap.put(aClass, null); @@ -349,7 +349,7 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase { final PsiFile createdFile = copy(psiFile, targetDirectory, copyClassName, map == null ? null : map.get(psiFile), choice); if (createdFile == null) return null; for (final PsiClass destination : ((PsiClassOwner)createdFile).getClasses()) { - if (destination instanceof SyntheticElement) { + if (isSynthetic(destination)) { continue; } PsiClass source = findByName(sources, destination.getName()); @@ -408,6 +408,10 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase { return newElement != null ? newElement : createdFiles.size() > 0 ? createdFiles.get(0) : null; } + protected static boolean isSynthetic(PsiClass aClass) { + return aClass instanceof SyntheticElement || !aClass.isPhysical(); + } + private static PsiFile copy(@NotNull PsiFile file, PsiDirectory directory, String name, String relativePath, int[] choice) { final String fileName = getNewFileName(file, name); if (relativePath != null && !relativePath.isEmpty()) { @@ -420,9 +424,10 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase { private static String getNewFileName(PsiFile file, String name) { if (name != null) { if (file instanceof PsiClassOwner) { - final PsiClass[] classes = ((PsiClassOwner)file).getClasses(); - if (classes.length > 0 && !(classes[0] instanceof SyntheticElement)) { - return name + "." + file.getViewProvider().getVirtualFile().getExtension(); + for (final PsiClass psiClass : ((PsiClassOwner)file).getClasses()) { + if (!isSynthetic(psiClass)) { + return name + "." + file.getViewProvider().getVirtualFile().getExtension(); + } } } return name; @@ -530,15 +535,14 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase { if (element instanceof PsiCompiledElement) return null; if (element instanceof PsiClassOwner) { PsiClass[] classes = ((PsiClassOwner)element).getClasses(); - if (classes.length > 0) { - for (final PsiClass aClass : classes) { - if (aClass instanceof SyntheticElement) { - return null; - } + ArrayList<PsiClass> buffer = new ArrayList<PsiClass>(); + for (final PsiClass aClass : classes) { + if (isSynthetic(aClass)) { + return null; } - - return classes; + buffer.add(aClass); } + return buffer.toArray(new PsiClass[buffer.size()]); } return element instanceof PsiClass ? new PsiClass[]{(PsiClass)element} : null; } diff --git a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java index b8f24bc16f1f..b3e43eb93938 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -59,6 +59,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra private Project myProject; + @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); int offset = editor.getCaretModel().getOffset(); @@ -77,6 +78,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra } } + @Override public void invoke(@NotNull final Project project, @NotNull PsiElement[] elements, DataContext dataContext) { if (elements.length != 1) return; @@ -101,6 +103,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra final List<MemberInfo> memberInfos = MemberInfo.extractClassMembers(mySubclass, new MemberInfo.Filter<PsiMember>() { + @Override public boolean includeMember(PsiMember element) { return true; } @@ -112,8 +115,10 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra if (!dialog.isOK() || !dialog.isExtractSuperclass()) return; CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { + @Override public void run() { final Runnable action = new Runnable() { + @Override public void run() { doRefactoring(project, mySubclass, dialog); } @@ -124,6 +129,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra } + @Override public boolean checkConflicts(final ExtractSuperclassDialog dialog) { final MemberInfo[] infos = ArrayUtil.toObjectArray(dialog.getSelectedMemberInfos(), MemberInfo.class); final PsiDirectory targetDirectory = dialog.getTargetDirectory(); @@ -136,9 +142,17 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra } final MultiMap<PsiElement,String> conflicts = new MultiMap<PsiElement, String>(); if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + @Override public void run() { - final PsiClass superClass = mySubclass.getExtendsListTypes().length > 0 || mySubclass instanceof PsiAnonymousClass ? mySubclass.getSuperClass() : null; - conflicts.putAllValues(PullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, targetPackage, targetDirectory, dialog.getContainmentVerifier(), false)); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + final PsiClass superClass = + mySubclass.getExtendsListTypes().length > 0 || mySubclass instanceof PsiAnonymousClass ? mySubclass.getSuperClass() : null; + conflicts.putAllValues(PullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, targetPackage, targetDirectory, + dialog.getContainmentVerifier(), false)); + } + }); } }, RefactoringBundle.message("detecting.possible.conflicts"), true, myProject)) return false; ExtractSuperClassUtil.checkSuperAccessible(targetDirectory, conflicts, mySubclass); @@ -168,6 +182,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra final SmartPsiElementPointer<PsiClass> classPointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(subclass); final SmartPsiElementPointer<PsiClass> interfacePointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(superclass); final Runnable turnRefsToSuperRunnable = new Runnable() { + @Override public void run() { ExtractClassUtil.askAndTurnRefsToSuper(project, classPointer, interfacePointer); } @@ -185,6 +200,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra return RefactoringBundle.message("extract.superclass.command.name", newName, DescriptiveNameUtil.getDescriptiveName(subclass)); } + @Override public boolean isEnabledOnElements(PsiElement[] elements) { return elements.length == 1 && elements[0] instanceof PsiClass && !((PsiClass) elements[0]).isInterface() &&!((PsiClass)elements[0]).isEnum(); diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineConstantFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineConstantFieldHandler.java index b82953534b8c..ddfb057460ab 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineConstantFieldHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineConstantFieldHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -17,6 +17,7 @@ package com.intellij.refactoring.inline; import com.intellij.codeInsight.TargetElementUtilBase; import com.intellij.lang.StdLanguages; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; @@ -35,10 +36,12 @@ import com.intellij.refactoring.util.CommonRefactoringUtil; public class InlineConstantFieldHandler extends JavaInlineActionHandler { private static final String REFACTORING_NAME = RefactoringBundle.message("inline.field.title"); + @Override public boolean canInlineElement(PsiElement element) { return element instanceof PsiField && StdLanguages.JAVA.equals(element.getLanguage()); } + @Override public void inlineElement(Project project, Editor editor, PsiElement element) { final PsiElement navigationElement = element.getNavigationElement(); final PsiField field = (PsiField)(navigationElement instanceof PsiField ? navigationElement : element); @@ -66,13 +69,18 @@ public class InlineConstantFieldHandler extends JavaInlineActionHandler { if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { - for (PsiReference reference : ReferencesSearch.search(field)) { - final PsiElement referenceElement = reference.getElement(); - if (!(referenceElement instanceof PsiExpression && PsiUtil.isAccessedForReading((PsiExpression)referenceElement))) { - hasWriteUsages.set(true); - break; + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + for (PsiReference reference : ReferencesSearch.search(field)) { + final PsiElement referenceElement = reference.getElement(); + if (!(referenceElement instanceof PsiExpression && PsiUtil.isAccessedForReading((PsiExpression)referenceElement))) { + hasWriteUsages.set(true); + break; + } + } } - } + }); } }, "Check if inline is possible...", true, project)) { return; diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java index 2b285553bc24..b8097d7376f6 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java @@ -200,7 +200,7 @@ public class InlineParameterHandler extends JavaInlineActionHandler { } if (!ApplicationManager.getApplication().isUnitTestMode()) { - String occurencesString = RefactoringBundle.message("occurences.string", occurrences.size()); + String occurencesString = RefactoringBundle.message("occurrences.string", occurrences.size()); String question = RefactoringBundle.message("inline.parameter.confirmation", psiParameter.getName(), constantExpression.getText()) + " " + occurencesString; RefactoringMessageDialog dialog = new RefactoringMessageDialog( diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassHandler.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassHandler.java index e17326844249..8d7995fbf1b0 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassHandler.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. @@ -91,7 +91,7 @@ public class InlineToAnonymousClassHandler extends JavaInlineActionHandler { }); } }, "Searching for class \"" + element.getQualifiedName() + "\" inheritors ...", true, element.getProject())) return false; - return inheritors.size() == 0; + return inheritors.isEmpty(); } @Override @@ -124,7 +124,12 @@ public class InlineToAnonymousClassHandler extends JavaInlineActionHandler { if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable(){ @Override public void run() { - errorMessage.set(getCannotInlineMessage(psiClass)); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + errorMessage.set(getCannotInlineMessage(psiClass)); + } + }); } }, "Check if inline is possible...", true, project)) return; if (errorMessage.get() != null) { diff --git a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java index de5efa573d8a..64afbfa17e84 100644 --- a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java @@ -27,6 +27,7 @@ import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.refactoring.util.javadoc.MethodJavaDocHelper; import com.intellij.usageView.UsageInfo; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.MultiMap; import java.util.ArrayList; import java.util.List; @@ -41,6 +42,20 @@ public class MakeMethodStaticProcessor extends MakeMethodOrClassStaticProcessor< super(project, method, settings); } + @Override + protected MultiMap<PsiElement, String> getConflictDescriptions(UsageInfo[] usages) { + MultiMap<PsiElement, String> descriptions = super.getConflictDescriptions(usages); + if (mySettings.isMakeClassParameter()) { + for (UsageInfo usage : usages) { + PsiElement element = usage.getElement(); + if (element instanceof PsiMethodReferenceExpression) { + descriptions.putValue(element, "Method reference will be corrupted"); + } + } + } + return descriptions; + } + protected void changeSelfUsage(SelfUsageInfo usageInfo) throws IncorrectOperationException { PsiElement parent = usageInfo.getElement().getParent(); LOG.assertTrue(parent instanceof PsiMethodCallExpression); diff --git a/java/java-impl/src/com/intellij/refactoring/memberPullUp/JavaPullUpHandler.java b/java/java-impl/src/com/intellij/refactoring/memberPullUp/JavaPullUpHandler.java index 2cbf7a0adcee..5a21d945fd79 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPullUp/JavaPullUpHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPullUp/JavaPullUpHandler.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. @@ -26,6 +26,7 @@ package com.intellij.refactoring.memberPullUp; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; @@ -55,6 +56,7 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog private PsiClass mySubclass; private Project myProject; + @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { int offset = editor.getCaretModel().getOffset(); editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); @@ -78,6 +80,7 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog } } + @Override public void invoke(@NotNull final Project project, @NotNull PsiElement[] elements, DataContext dataContext) { if (elements.length != 1) return; myProject = project; @@ -130,6 +133,7 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog mySubclass = aClass; MemberInfoStorage memberInfoStorage = new MemberInfoStorage(mySubclass, new MemberInfo.Filter<PsiMember>() { + @Override public boolean includeMember(PsiMember element) { return true; } @@ -152,6 +156,7 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog + @Override public boolean checkConflicts(final PullUpDialog dialog) { final List<MemberInfo> infos = dialog.getSelectedMemberInfos(); final MemberInfo[] memberInfos = infos.toArray(new MemberInfo[infos.size()]); @@ -159,11 +164,18 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog if (!checkWritable(superClass, memberInfos)) return false; final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>(); if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + @Override public void run() { - final PsiDirectory targetDirectory = superClass.getContainingFile().getContainingDirectory(); - final PsiPackage targetPackage = targetDirectory != null ? JavaDirectoryService.getInstance().getPackage(targetDirectory) : null; - conflicts - .putAllValues(PullUpConflictsUtil.checkConflicts(memberInfos, mySubclass, superClass, targetPackage, targetDirectory, dialog.getContainmentVerifier())); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + final PsiDirectory targetDirectory = superClass.getContainingFile().getContainingDirectory(); + final PsiPackage targetPackage = targetDirectory != null ? JavaDirectoryService.getInstance().getPackage(targetDirectory) : null; + conflicts + .putAllValues(PullUpConflictsUtil.checkConflicts(memberInfos, mySubclass, superClass, targetPackage, targetDirectory, dialog.getContainmentVerifier())); + } + }); + } }, RefactoringBundle.message("detecting.possible.conflicts"), true, myProject)) return false; if (!conflicts.isEmpty()) { @@ -185,6 +197,7 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog return true; } + @Override public boolean isEnabledOnElements(PsiElement[] elements) { /* if (elements.length == 1) { diff --git a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpProcessor.java b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpProcessor.java index 4531e391f838..353898cafe51 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpProcessor.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. @@ -68,7 +68,7 @@ public class PullUpProcessor extends BaseRefactoringProcessor implements PullUpD private final DocCommentPolicy myJavaDocPolicy; private Set<PsiMember> myMembersAfterMove = null; private Set<PsiMember> myMovedMembers = null; - private Map<Language, PullUpHelper<MemberInfo>> myProcessors = ContainerUtil.newHashMap(); + private final Map<Language, PullUpHelper<MemberInfo>> myProcessors = ContainerUtil.newHashMap(); public PullUpProcessor(PsiClass sourceClass, PsiClass targetSuperClass, MemberInfo[] membersToMove, DocCommentPolicy javaDocPolicy) { super(sourceClass.getProject()); @@ -78,11 +78,13 @@ public class PullUpProcessor extends BaseRefactoringProcessor implements PullUpD myJavaDocPolicy = javaDocPolicy; } + @Override @NotNull protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) { return new PullUpUsageViewDescriptor(); } + @Override @NotNull protected UsageInfo[] findUsages() { final List<UsageInfo> result = new ArrayList<UsageInfo>(); @@ -125,6 +127,7 @@ public class PullUpProcessor extends BaseRefactoringProcessor implements PullUpD return data; } + @Override protected void performRefactoring(UsageInfo[] usages) { moveMembersToBase(); moveFieldInitializations(); @@ -148,29 +151,35 @@ public class PullUpProcessor extends BaseRefactoringProcessor implements PullUpD ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @Override public void run() { - final Query<PsiClass> search = ClassInheritorsSearch.search(myTargetSuperClass); - final Set<VirtualFile> hierarchyFiles = new HashSet<VirtualFile>(); - for (PsiClass aClass : search) { - final PsiFile containingFile = aClass.getContainingFile(); - if (containingFile != null) { - final VirtualFile virtualFile = containingFile.getVirtualFile(); - if (virtualFile != null) { - hierarchyFiles.add(virtualFile); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + final Query<PsiClass> search = ClassInheritorsSearch.search(myTargetSuperClass); + final Set<VirtualFile> hierarchyFiles = new HashSet<VirtualFile>(); + for (PsiClass aClass : search) { + final PsiFile containingFile = aClass.getContainingFile(); + if (containingFile != null) { + final VirtualFile virtualFile = containingFile.getVirtualFile(); + if (virtualFile != null) { + hierarchyFiles.add(virtualFile); + } + } + } + final Set<PsiMember> methodsToSearchDuplicates = new HashSet<PsiMember>(); + for (PsiMember psiMember : myMembersAfterMove) { + if (psiMember instanceof PsiMethod && psiMember.isValid() && ((PsiMethod)psiMember).getBody() != null) { + methodsToSearchDuplicates.add(psiMember); + } } - } - } - final Set<PsiMember> methodsToSearchDuplicates = new HashSet<PsiMember>(); - for (PsiMember psiMember : myMembersAfterMove) { - if (psiMember instanceof PsiMethod && psiMember.isValid() && ((PsiMethod)psiMember).getBody() != null) { - methodsToSearchDuplicates.add(psiMember); - } - } - MethodDuplicatesHandler.invokeOnScope(myProject, methodsToSearchDuplicates, new AnalysisScope(myProject, hierarchyFiles), true); + MethodDuplicatesHandler.invokeOnScope(myProject, methodsToSearchDuplicates, new AnalysisScope(myProject, hierarchyFiles), true); + } + }); } }, MethodDuplicatesHandler.REFACTORING_NAME, true, myProject); } + @Override protected String getCommandName() { return RefactoringBundle.message("pullUp.command", DescriptiveNameUtil.getDescriptiveName(mySourceClass)); } @@ -303,19 +312,23 @@ public class PullUpProcessor extends BaseRefactoringProcessor implements PullUpD } private class PullUpUsageViewDescriptor implements UsageViewDescriptor { + @Override public String getProcessedElementsHeader() { return "Pull up members from"; } + @Override @NotNull public PsiElement[] getElements() { return new PsiElement[]{mySourceClass}; } + @Override public String getCodeReferencesText(int usagesCount, int filesCount) { return "Class to pull up members to \"" + RefactoringUIUtil.getDescription(myTargetSuperClass, true) + "\""; } + @Override public String getCommentReferencesText(int usagesCount, int filesCount) { return null; } diff --git a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java index ca3298bc97b2..bb09c69c9fcc 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.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. @@ -19,6 +19,7 @@ import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.ChangeContextUtil; import com.intellij.codeInsight.intention.impl.CreateClassDialog; import com.intellij.codeInsight.intention.impl.CreateSubclassAction; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; @@ -72,10 +73,12 @@ public class PushDownProcessor extends BaseRefactoringProcessor { myJavaDocPolicy = javaDocPolicy; } + @Override protected String getCommandName() { return JavaPushDownHandler.REFACTORING_NAME; } + @Override @NotNull protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) { return new PushDownUsageViewDescriptor(myClass); @@ -116,6 +119,7 @@ public class PushDownProcessor extends BaseRefactoringProcessor { return data; } + @Override @NotNull protected UsageInfo[] findUsages() { final PsiClass[] inheritors = ClassInheritorsSearch.search(myClass, false).toArray(PsiClass.EMPTY_ARRAY); @@ -147,6 +151,7 @@ public class PushDownProcessor extends BaseRefactoringProcessor { return false; } + @Override protected boolean preprocessUsages(final Ref<UsageInfo[]> refUsages) { final UsageInfo[] usagesIn = refUsages.get(); final PushDownConflicts pushDownConflicts = new PushDownConflicts(myClass, myMemberInfos); @@ -177,13 +182,19 @@ public class PushDownProcessor extends BaseRefactoringProcessor { } } Runnable runnable = new Runnable() { + @Override public void run() { - for (UsageInfo usage : usagesIn) { - final PsiElement element = usage.getElement(); - if (element instanceof PsiClass) { - pushDownConflicts.checkTargetClassConflicts((PsiClass)element, usagesIn.length > 1, element); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + for (UsageInfo usage : usagesIn) { + final PsiElement element = usage.getElement(); + if (element instanceof PsiClass) { + pushDownConflicts.checkTargetClassConflicts((PsiClass)element, usagesIn.length > 1, element); + } + } } - } + }); } }; @@ -204,6 +215,7 @@ public class PushDownProcessor extends BaseRefactoringProcessor { return showConflicts(pushDownConflicts.getConflicts(), usagesIn); } + @Override protected void refreshElements(PsiElement[] elements) { if(elements.length == 1 && elements[0] instanceof PsiClass) { myClass = (PsiClass) elements[0]; @@ -213,6 +225,7 @@ public class PushDownProcessor extends BaseRefactoringProcessor { } } + @Override protected void performRefactoring(UsageInfo[] usages) { try { encodeRefs(); @@ -509,6 +522,7 @@ public class PushDownProcessor extends BaseRefactoringProcessor { decodeRefs(newMember, targetClass); //rebind imports first Collections.sort(refsToRebind, new Comparator<PsiReference>() { + @Override public int compare(PsiReference o1, PsiReference o2) { return PsiUtil.BY_POSITION.compare(o1.getElement(), o2.getElement()); } diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java index 3e92a19373ab..844eb2dc0611 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -88,7 +88,7 @@ public class MoveClassesOrPackagesImpl { if (element instanceof PsiDirectory) { PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage((PsiDirectory)element); LOG.assertTrue(aPackage != null); - if (aPackage.getQualifiedName().length() == 0) { //is default package + if (aPackage.getQualifiedName().isEmpty()) { //is default package String message = RefactoringBundle.message("move.package.refactoring.cannot.be.applied.to.default.package"); CommonRefactoringUtil.showErrorMessage(RefactoringBundle.message("move.title"), message, HelpID.getMoveHelpID(element), project); return null; @@ -167,7 +167,7 @@ public class MoveClassesOrPackagesImpl { message.append(RefactoringBundle.message("do.you.wish.to.continue")); int ret = Messages.showYesNoDialog(project, message.toString(), RefactoringBundle.message("warning.title"), Messages.getWarningIcon()); - if (ret != 0) { + if (ret != Messages.YES) { return false; } } @@ -323,8 +323,15 @@ public class MoveClassesOrPackagesImpl { if (selectedTarget == null) return; final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>(); final Runnable analyzeConflicts = new Runnable() { + @Override public void run() { - RefactoringConflictsUtil.analyzeModuleConflicts(project, Arrays.asList(directories), UsageInfo.EMPTY_ARRAY, selectedTarget, conflicts); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + RefactoringConflictsUtil + .analyzeModuleConflicts(project, Arrays.asList(directories), UsageInfo.EMPTY_ARRAY, selectedTarget, conflicts); + } + }); } }; if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(analyzeConflicts, "Analyze Module Conflicts...", true, project)) { @@ -345,8 +352,10 @@ public class MoveClassesOrPackagesImpl { final Ref<IncorrectOperationException> ex = Ref.create(null); final String commandDescription = RefactoringBundle.message("moving.directories.command"); Runnable runnable = new Runnable() { + @Override public void run() { ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override public void run() { LocalHistoryAction a = LocalHistory.getInstance().startAction(commandDescription); try { diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java index f398dfdd115a..0e02b8f94e28 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java @@ -23,7 +23,6 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.wm.WindowManager; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PackageScope; @@ -48,7 +47,6 @@ import com.intellij.refactoring.util.classRefs.ClassReferenceScanner; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.usageView.UsageViewUtil; -import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import com.intellij.util.VisibilityUtil; @@ -472,9 +470,7 @@ public class MoveClassesOrPackagesProcessor extends BaseRefactoringProcessor { } protected boolean isPreviewUsages(UsageInfo[] usages) { - if (UsageViewUtil.hasNonCodeUsages(usages)) { - WindowManager.getInstance().getStatusBar(myProject).setInfo( - RefactoringBundle.message("occurrences.found.in.comments.strings.and.non.java.files")); + if (UsageViewUtil.reportNonRegularUsages(usages, myProject)) { return true; } else { diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassJavaUsagesHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassJavaUsagesHandler.java new file mode 100644 index 000000000000..0589e6d8e187 --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassJavaUsagesHandler.java @@ -0,0 +1,58 @@ +/* + * 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.move.moveInner; + +import com.intellij.psi.*; +import com.intellij.refactoring.util.RefactoringChangeUtil; +import com.intellij.usageView.UsageInfo; +import org.jetbrains.annotations.NotNull; + +public class MoveInnerClassJavaUsagesHandler implements MoveInnerClassUsagesHandler { + @Override + public void correctInnerClassUsage(@NotNull UsageInfo usage, @NotNull PsiClass outerClass) { + PsiElement refElement = usage.getElement(); + if (refElement == null) return; + + PsiManager manager = refElement.getManager(); + + PsiElement refParent = refElement.getParent(); + if (refParent instanceof PsiNewExpression || refParent instanceof PsiAnonymousClass) { + PsiNewExpression newExpr = refParent instanceof PsiNewExpression + ? (PsiNewExpression)refParent + : (PsiNewExpression)refParent.getParent(); + + PsiExpressionList argList = newExpr.getArgumentList(); + + if (argList != null) { // can happen in incomplete code + if (newExpr.getQualifier() == null) { + PsiThisExpression thisExpr; + PsiClass parentClass = RefactoringChangeUtil.getThisClass(newExpr); + if (outerClass.equals(parentClass)) { + thisExpr = RefactoringChangeUtil.createThisExpression(manager, null); + } + else { + thisExpr = RefactoringChangeUtil.createThisExpression(manager, outerClass); + } + argList.addAfter(thisExpr, null); + } + else { + argList.addAfter(newExpr.getQualifier(), null); + newExpr.getQualifier().delete(); + } + } + } + } +}
\ No newline at end of file diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassUsagesHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassUsagesHandler.java new file mode 100644 index 000000000000..97946456d6fb --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassUsagesHandler.java @@ -0,0 +1,28 @@ +/* + * 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.move.moveInner; + +import com.intellij.lang.LanguageExtension; +import com.intellij.psi.PsiClass; +import com.intellij.usageView.UsageInfo; +import org.jetbrains.annotations.NotNull; + +public interface MoveInnerClassUsagesHandler { + LanguageExtension<MoveInnerClassUsagesHandler> EP_NAME = + new LanguageExtension<MoveInnerClassUsagesHandler>("com.intellij.refactoring.moveInnerClassUsagesHandler"); + + void correctInnerClassUsage(@NotNull UsageInfo usage, @NotNull PsiClass outerClass); +}
\ No newline at end of file diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java index d4239e578016..d56b8c02844e 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java @@ -214,35 +214,11 @@ public class MoveInnerProcessor extends BaseRefactoringProcessor { // correct references in usages for (UsageInfo usage : usages) { - if (usage.isNonCodeUsage) continue; - PsiElement refElement = usage.getElement(); - if (myParameterNameOuterClass != null) { // should pass outer as parameter - PsiElement refParent = refElement.getParent(); - if (refParent instanceof PsiNewExpression || refParent instanceof PsiAnonymousClass) { - PsiNewExpression newExpr = refParent instanceof PsiNewExpression - ? (PsiNewExpression)refParent - : (PsiNewExpression)refParent.getParent(); - - PsiExpressionList argList = newExpr.getArgumentList(); - - if (argList != null) { // can happen in incomplete code - if (newExpr.getQualifier() == null) { - PsiThisExpression thisExpr; - PsiClass parentClass = RefactoringChangeUtil.getThisClass(newExpr); - if (myOuterClass.equals(parentClass)) { - thisExpr = RefactoringChangeUtil.createThisExpression(manager, null); - } - else { - thisExpr = RefactoringChangeUtil.createThisExpression(manager, myOuterClass); - } - argList.addAfter(thisExpr, null); - } - else { - argList.addAfter(newExpr.getQualifier(), null); - newExpr.getQualifier().delete(); - } - } - } + if (usage.isNonCodeUsage || myParameterNameOuterClass == null) continue; // should pass outer as parameter + + MoveInnerClassUsagesHandler usagesHandler = MoveInnerClassUsagesHandler.EP_NAME.forLanguage(usage.getElement().getLanguage()); + if (usagesHandler != null) { + usagesHandler.correctInnerClassUsage(usage, myOuterClass); } } @@ -554,4 +530,4 @@ public class MoveInnerProcessor extends BaseRefactoringProcessor { public String getParameterName() { return myParameterNameOuterClass; } -} +}
\ No newline at end of file diff --git a/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java b/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java index 1ed6de9ced09..b4142228f01f 100644 --- a/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java +++ b/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.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. @@ -69,6 +69,7 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces private final String mySuperClassName; private final List<UsageInfo> myVariablesUsages = new ArrayList<UsageInfo>(); + @Override protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) { UsageInfo[] usages = refUsages.get(); List<UsageInfo> filtered = new ArrayList<UsageInfo>(); @@ -93,8 +94,14 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces } Runnable runnable = new Runnable() { + @Override public void run() { - myVariableRenamer.findUsages(myVariablesUsages, false, false); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + myVariableRenamer.findUsages(myVariablesUsages, false, false); + } + }); } }; @@ -338,6 +345,7 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces if (substitutor == null) return; final LocalSearchScope baseScope = new LocalSearchScope(ownerClass); ReferencesSearch.search(typeParameter, baseScope).forEach(new Processor<PsiReference>() { + @Override public boolean process(final PsiReference ref) { final PsiElement element = ref.getElement(); final PsiElement parent = element.getParent(); @@ -708,6 +716,7 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces } class Colorer implements OneEndFunctor { + @Override public Mark compute(Mark from, Mark edge, Mark to) { VisitMark mark = new VisitMark((VisitMark)to); @@ -737,6 +746,7 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces private boolean myVisited; private final PsiElement myElement; + @Override public boolean coincidesWith(Mark x) { return ((VisitMark)x).myVisited == myVisited; } @@ -773,10 +783,12 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces myMark = new VisitMark(x); } + @Override public Mark getMark() { return myMark; } + @Override public void setMark(Mark x) { myMark = (VisitMark)x; } diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java index 609a981b7bf4..2998ec6b0f07 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java @@ -88,28 +88,32 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor { final Editor editor, final TypeMigrationRules rules, final PsiElement root) { + final PsiFile containingFile = root.getContainingFile(); final TypeMigrationProcessor processor = new TypeMigrationProcessor(project, root, rules) { @Override public void performRefactoring(final UsageInfo[] usages) { super.performRefactoring(usages); - ApplicationManager.getApplication().invokeLater(new Runnable() { - public void run() { - final List<PsiElement> result = new ArrayList<PsiElement>(); - for (UsageInfo usage : usages) { - final PsiElement element = usage.getElement(); - if (element instanceof PsiMethod) { - result.add(((PsiMethod)element).getReturnTypeElement()); - } - else if (element instanceof PsiVariable) { - result.add(((PsiVariable)element).getTypeElement()); - } - else if (element != null) { - result.add(element); + if (editor != null) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + final List<PsiElement> result = new ArrayList<PsiElement>(); + for (UsageInfo usage : usages) { + final PsiElement element = usage.getElement(); + if (element == null || containingFile != element.getContainingFile()) continue; + if (element instanceof PsiMethod) { + result.add(((PsiMethod)element).getReturnTypeElement()); + } + else if (element instanceof PsiVariable) { + result.add(((PsiVariable)element).getTypeElement()); + } + else { + result.add(element); + } } + RefactoringUtil.highlightAllOccurrences(project, PsiUtilCore.toPsiElementArray(result), editor); } - if (editor != null) RefactoringUtil.highlightAllOccurrences(project, PsiUtilCore.toPsiElementArray(result), editor); - } - }); + }); + } } }; processor.run(); 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 ca01331d3e94..ed08349519a7 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java @@ -677,7 +677,7 @@ public class RefactoringUtil { public static PsiExpression convertInitializerToNormalExpression(PsiExpression expression, PsiType forcedReturnType) throws IncorrectOperationException { - if (expression instanceof PsiArrayInitializerExpression) { + if (expression instanceof PsiArrayInitializerExpression && (forcedReturnType == null || forcedReturnType instanceof PsiArrayType)) { return createNewExpressionFromArrayInitializer((PsiArrayInitializerExpression)expression, forcedReturnType); } return expression; diff --git a/java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.java b/java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.java index c75c30dfb470..b65932aeaa81 100644 --- a/java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.java +++ b/java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.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. @@ -178,8 +178,13 @@ public class SliceNullnessAnalyzer { node(element, map).add(node(duplicate, map)); } else { - SliceUsage sliceUsage = element.getValue(); - final PsiElement value = sliceUsage.getElement(); + final SliceUsage sliceUsage = element.getValue(); + final PsiElement value = ApplicationManager.getApplication().runReadAction(new Computable<PsiElement>() { + @Override + public PsiElement compute() { + return sliceUsage.getElement(); + } + }); Nullness nullness = ApplicationManager.getApplication().runReadAction(new Computable<Nullness>() { @Override public Nullness compute() { diff --git a/java/java-impl/src/com/intellij/slicer/SliceUtil.java b/java/java-impl/src/com/intellij/slicer/SliceUtil.java index 6d556b5f9681..014bbdd0ce71 100644 --- a/java/java-impl/src/com/intellij/slicer/SliceUtil.java +++ b/java/java-impl/src/com/intellij/slicer/SliceUtil.java @@ -138,7 +138,8 @@ public class SliceUtil { } } if (expression instanceof PsiMethodCallExpression) { // ctr call can't return value or be container get, so don't use PsiCall here - Flow anno = isMethodFlowAnnotated(((PsiMethodCallExpression)expression).resolveMethod()); + PsiMethod method = ((PsiMethodCallExpression)expression).resolveMethod(); + Flow anno = isMethodFlowAnnotated(method); if (anno != null) { String target = anno.target(); if (target.equals(Flow.DEFAULT_TARGET)) target = Flow.RETURN_METHOD_TARGET; diff --git a/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java b/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java index 92fe17ad085e..f75fb83cf54e 100644 --- a/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java +++ b/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java @@ -47,14 +47,7 @@ public class JavaTestFinder implements TestFinder { PsiClass klass = findSourceElement(element); if (klass == null) return Collections.emptySet(); - GlobalSearchScope scope; - Module module = getModule(element); - if (module != null) { - scope = GlobalSearchScope.moduleWithDependenciesScope(module); - } - else { - scope = GlobalSearchScope.projectScope(element.getProject()); - } + GlobalSearchScope scope = getSearchScope(element); PsiShortNamesCache cache = PsiShortNamesCache.getInstance(element.getProject()); @@ -70,6 +63,16 @@ public class JavaTestFinder implements TestFinder { return TestFinderHelper.getSortedElements(classesWithWeights, false); } + protected GlobalSearchScope getSearchScope(PsiElement element) { + final Module module = getModule(element); + if (module != null) { + return GlobalSearchScope.moduleWithDependenciesScope(module); + } + else { + return GlobalSearchScope.projectScope(element.getProject()); + } + } + private static boolean isTestSubjectClass(PsiClass klass) { if (klass.isAnnotationType() || TestFrameworks.getInstance().isTestClass(klass)) { return false; @@ -90,15 +93,8 @@ public class JavaTestFinder implements TestFinder { return TestFinderHelper.getSortedElements(classesWithProximities, true); } - private static boolean collectTests(PsiClass klass, Processor<Pair<? extends PsiNamedElement, Integer>> processor) { - GlobalSearchScope scope; - Module module = getModule(klass); - if (module != null) { - scope = GlobalSearchScope.moduleWithDependentsScope(module); - } - else { - scope = GlobalSearchScope.projectScope(klass.getProject()); - } + private boolean collectTests(PsiClass klass, Processor<Pair<? extends PsiNamedElement, Integer>> processor) { + GlobalSearchScope scope = getSearchScope(klass); PsiShortNamesCache cache = PsiShortNamesCache.getInstance(klass.getProject()); @@ -131,13 +127,4 @@ public class JavaTestFinder implements TestFinder { public boolean isTest(@NotNull PsiElement element) { return TestIntegrationUtils.isTest(element); } - - public static boolean hasTestsForClass(PsiClass aClass) { - return collectTests(aClass, new CommonProcessors.FindProcessor<Pair<? extends PsiNamedElement, Integer>>() { - @Override - protected boolean accept(Pair<? extends PsiNamedElement, Integer> pair) { - return true; - } - }); - } } diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java index d32864676c55..cceceb24c826 100644 --- a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java +++ b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java @@ -109,11 +109,7 @@ public class CreateTestAction extends PsiElementBaseIntentionAction { propertiesComponent.setValue(CREATE_TEST_IN_THE_SAME_ROOT, String.valueOf(true)); } - final CreateTestDialog d = new CreateTestDialog(project, - getText(), - srcClass, - srcPackage, - srcModule); + final CreateTestDialog d = createTestDialog(project, srcModule, srcClass, srcPackage); d.show(); if (!d.isOK()) return; @@ -127,6 +123,10 @@ public class CreateTestAction extends PsiElementBaseIntentionAction { }, CodeInsightBundle.message("intention.create.test"), this); } + protected CreateTestDialog createTestDialog(Project project, Module srcModule, PsiClass srcClass, PsiPackage srcPackage) { + return new CreateTestDialog(project, getText(), srcClass, srcPackage, srcModule); + } + protected static void checkForTestRoots(Module srcModule, Set<VirtualFile> testFolders) { checkForTestRoots(srcModule, testFolders, new HashSet<Module>()); } diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java index cf4c67911208..5be9ce379705 100644 --- a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java +++ b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java @@ -181,7 +181,7 @@ public class CreateTestDialog extends DialogWrapper { } }); - myTargetClassNameField = new EditorTextField(targetClass.getName() + "Test"); + myTargetClassNameField = new EditorTextField(suggestTestClassName(targetClass)); myTargetClassNameField.getDocument().addDocumentListener(new DocumentAdapter() { @Override public void documentChanged(DocumentEvent e) { @@ -217,6 +217,10 @@ public class CreateTestDialog extends DialogWrapper { updateMethodsTable(); } + protected String suggestTestClassName(PsiClass targetClass) { + return targetClass.getName() + "Test"; + } + private boolean isSuperclassSelectedManually() { String superClass = mySuperClassField.getText(); if (StringUtil.isEmptyOrSpaces(superClass)) { |