diff --git a/.idea/modules.xml b/.idea/modules.xml index d48c568c7a5d..82283e971251 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,12 +2,12 @@ - + - + @@ -20,46 +20,50 @@ - - + + - + - + - - - - + + + + + + + + - + - - - + + + - - + + - - - + + + @@ -71,15 +75,15 @@ - + - - + + - - + + @@ -90,8 +94,8 @@ - - + + diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index ca27a5c4ab78..514c3cda7d2b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -529,6 +529,7 @@ public class HighlightMethodUtil { return containingClass == null ? method.getContainingFile().getName() : HighlightUtil.formatClass(containingClass, false); } + @Language("HTML") private static String createAmbiguousMethodHtmlTooltipMethodRow(final MethodCandidateInfo methodCandidate) { PsiMethod method = methodCandidate.getElement(); PsiParameter[] parameters = method.getParameterList().getParameters(); @@ -565,6 +566,7 @@ public class HighlightMethodUtil { PsiExpression[] expressions = list.getExpressions(); int cols = Math.max(parameters.length, expressions.length); + @Language("HTML") @NonNls String parensizedName = methodName + (parameters.length == 0 ? "( ) " : ""); return JavaErrorMessages.message( "argument.mismatch.html.tooltip", @@ -576,7 +578,7 @@ public class HighlightMethodUtil { } private static String esctrim(@NotNull String s) { - return StringUtil.first(XmlStringUtil.escapeString(s), 40, true); + return XmlStringUtil.escapeString(StringUtil.first(s, 40, true)); } private static String createMismatchedArgumentsHtmlTooltip(PsiExpressionList list, @@ -592,6 +594,7 @@ public class HighlightMethodUtil { } } + @Language("HTML") private static String createLongMismatchedArgumentsHtmlTooltip(PsiExpressionList list, PsiParameter[] parameters, String methodName, @@ -599,22 +602,21 @@ public class HighlightMethodUtil { PsiClass aClass) { PsiExpression[] expressions = list.getExpressions(); - @NonNls @Language("HTML") + @NonNls String s = "" + - " "+ - " " - +" " + ""+ + ""+ + "" ; - for (int i = 0; i < Math.max(parameters.length,expressions.length); i++) { PsiParameter parameter = i < parameters.length ? parameters[i] : null; PsiExpression expression = i < expressions.length ? expressions[i] : null; @NonNls String mismatchColor = showShortType(i, parameters, expressions, substitutor) ? null : "red"; - s += ""; + s += ""; s += ""; } - s+= "
" + methodName + "() in " + HighlightUtil.formatClass(aClass, false) +" cannot be applied to:
Expected
Parameters:
Actual
Arguments:

" + + "" + methodName + "() in " + HighlightUtil.formatClass(aClass, false) +" cannot be applied to:" + + "
Expected
Parameters:
Actual
Arguments:

"; if (parameter != null) { String name = parameter.getName(); @@ -651,10 +653,11 @@ public class HighlightMethodUtil { s += "
"; + s+= ""; return s; } + @Language("HTML") private static String createMismatchedArgsHtmlTooltipArgumentsRow(final PsiExpression[] expressions, final PsiParameter[] parameters, final PsiSubstitutor substitutor, final int cols) { @NonNls String ms = ""; @@ -678,6 +681,7 @@ public class HighlightMethodUtil { return ms; } + @Language("HTML") private static String createMismatchedArgsHtmlTooltipParamsRow(final PsiParameter[] parameters, final PsiSubstitutor substitutor, final PsiExpression[] expressions) { diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java index 6ce642719400..2f18ccf88cce 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java @@ -636,11 +636,7 @@ public class ExtractMethodProcessor implements MatchProvider { if (myNullConditionalCheck) { final String varName = myOutputVariable.getName(); if (isDeclaredInside(myOutputVariable)) { - PsiDeclarationStatement statement = (PsiDeclarationStatement)myElementFactory - .createStatementFromText(myOutputVariable.getType().getCanonicalText() + " " + varName + "=x;", null); - statement = (PsiDeclarationStatement)addToMethodCallLocation(statement); - myMethodCall = - (PsiMethodCallExpression)((PsiLocalVariable)statement.getDeclaredElements()[0]).getInitializer().replace(myMethodCall); + declareVariableAtMethodCallLocation(varName); } else { PsiExpressionStatement assignmentExpression = @@ -676,12 +672,7 @@ public class ExtractMethodProcessor implements MatchProvider { myMethodCall = (PsiMethodCallExpression)assignment.getRExpression().replace(myMethodCall); } else { - PsiDeclarationStatement statement = - myElementFactory.createVariableDeclarationStatement(name, myOutputVariable.getType(), myMethodCall); - statement = (PsiDeclarationStatement)addToMethodCallLocation(statement); - PsiVariable var = (PsiVariable)statement.getDeclaredElements()[0]; - myMethodCall = (PsiMethodCallExpression)var.getInitializer(); - var.getModifierList().replace(myOutputVariable.getModifierList()); + declareVariableAtMethodCallLocation(name); } } else if (myHasReturnStatementOutput) { @@ -737,6 +728,15 @@ public class ExtractMethodProcessor implements MatchProvider { } + private void declareVariableAtMethodCallLocation(String name) { + PsiDeclarationStatement statement = + myElementFactory.createVariableDeclarationStatement(name, myOutputVariable.getType(), myMethodCall); + statement = (PsiDeclarationStatement)addToMethodCallLocation(statement); + PsiVariable var = (PsiVariable)statement.getDeclaredElements()[0]; + myMethodCall = (PsiMethodCallExpression)var.getInitializer(); + var.getModifierList().replace(myOutputVariable.getModifierList()); + } + private void adjustFinalParameters(final PsiMethod method) throws IncorrectOperationException { final IncorrectOperationException[] exc = new IncorrectOperationException[1]; exc[0] = 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 70641e1f052f..52e2f3fff772 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java @@ -133,8 +133,8 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra else { targetPackage = null; } - MultiMap conflicts = - PullUpConflictsUtil.checkConflicts(infos, mySubclass, null, targetPackage, targetDirectory, dialog.getContainmentVerifier()); + final MultiMap conflicts = + PullUpConflictsUtil.checkConflicts(infos, mySubclass, mySubclass.getSuperClass(), targetPackage, targetDirectory, dialog.getContainmentVerifier()); if (!conflicts.isEmpty()) { ConflictsDialog conflictsDialog = new ConflictsDialog(myProject, conflicts); conflictsDialog.show(); diff --git a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpHelper.java b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpHelper.java index f05c59913260..8b5b90821a0a 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpHelper.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpHelper.java @@ -30,6 +30,7 @@ import com.intellij.codeInsight.PsiEquivalenceUtil; import com.intellij.codeInsight.intention.AddAnnotationFix; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Key; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; @@ -60,6 +61,7 @@ import java.util.*; public class PullUpHelper extends BaseRefactoringProcessor{ private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.memberPullUp.PullUpHelper"); + private static final Key PRESERVE_QUALIFIER = Key.create("PRESERVE_QUALIFIER"); private final PsiClass mySourceClass; private final PsiClass myTargetSuperClass; private final boolean myIsTargetInterface; @@ -234,6 +236,20 @@ public class PullUpHelper extends BaseRefactoringProcessor{ ChangeContextUtil.decodeContextInfo(myTargetSuperClass, null, null); for (final PsiMember movedMember : myMembersAfterMove) { + movedMember.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitReferenceExpression(PsiReferenceExpression expression) { + final PsiExpression qualifierExpression = expression.getQualifierExpression(); + if (qualifierExpression != null) { + final Boolean preserveQualifier = qualifierExpression.getCopyableUserData(PRESERVE_QUALIFIER); + if (preserveQualifier != null && !preserveQualifier) { + qualifierExpression.delete(); + return; + } + } + super.visitReferenceExpression(expression); + } + }); final JavaRefactoringListenerManager listenerManager = JavaRefactoringListenerManager.getInstance(movedMember.getProject()); ((JavaRefactoringListenerManagerImpl)listenerManager).fireMemberMoved(mySourceClass, movedMember); } @@ -632,7 +648,7 @@ public class PullUpHelper extends BaseRefactoringProcessor{ } private void fixReferencesToStatic(PsiElement classMember, Set movedMembers) throws IncorrectOperationException { - StaticReferencesCollector collector = new StaticReferencesCollector(movedMembers); + final StaticReferencesCollector collector = new StaticReferencesCollector(movedMembers); classMember.accept(collector); ArrayList refs = collector.getReferences(); ArrayList members = collector.getReferees(); @@ -649,18 +665,19 @@ public class PullUpHelper extends BaseRefactoringProcessor{ (PsiReferenceExpression) factory.createExpressionFromText ("a." + ((PsiNamedElement) namedElement).getName(), null); - final PsiExpression qualifierExpression = newRef.getQualifierExpression(); + PsiExpression qualifierExpression = newRef.getQualifierExpression(); assert qualifierExpression != null; - qualifierExpression.replace(factory.createReferenceExpression(aClass)); + qualifierExpression = (PsiExpression)qualifierExpression.replace(factory.createReferenceExpression(aClass)); + qualifierExpression.putCopyableUserData(PRESERVE_QUALIFIER, ref.isQualified()); ref.replace(newRef); } } } private class StaticReferencesCollector extends ClassMemberReferencesVisitor { - ArrayList myReferences; - ArrayList myReferees; - ArrayList myRefereeClasses; + private ArrayList myReferences; + private ArrayList myReferees; + private ArrayList myRefereeClasses; private final Set myMovedMembers; private StaticReferencesCollector(Set movedMembers) { @@ -684,7 +701,6 @@ public class PullUpHelper extends BaseRefactoringProcessor{ } protected void visitClassMemberReferenceElement(PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) { - if (classMember instanceof PsiClass) return; if (classMember.hasModifierProperty(PsiModifier.STATIC)) { if (!myMovedMembers.contains(classMember) && RefactoringHierarchyUtil.isMemberBetween(myTargetSuperClass, mySourceClass, classMember)) { @@ -692,7 +708,7 @@ public class PullUpHelper extends BaseRefactoringProcessor{ myReferees.add(classMember); myRefereeClasses.add(classMember.getContainingClass()); } - else if ((myMovedMembers.contains(classMember) || myMembersAfterMove.contains(classMember)) && classMemberReference.isQualified()) { + else if (myMovedMembers.contains(classMember) || myMembersAfterMove.contains(classMember)) { myReferences.add(classMemberReference); myReferees.add(classMember); myRefereeClasses.add(myTargetSuperClass); diff --git a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java index 30f404a01a7f..41f53f6631d7 100644 --- a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java @@ -90,7 +90,7 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto final PsiElement element = reference.getElement(); final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(element, PsiNewExpression.class); if (newExpression != null && !PsiTreeUtil.isAncestor(builderClass, element, false)) { - usages.add(new ReplaceConstructorWithSettersChainInfo(newExpression, myClassName, myParametersMap)); + usages.add(new ReplaceConstructorWithSettersChainInfo(newExpression, StringUtil.getQualifiedName(myPackageName, myClassName), myParametersMap)); } } } diff --git a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/usageInfo/ReplaceConstructorWithSettersChainInfo.java b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/usageInfo/ReplaceConstructorWithSettersChainInfo.java index 0510863beb37..45e6624187ea 100644 --- a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/usageInfo/ReplaceConstructorWithSettersChainInfo.java +++ b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/usageInfo/ReplaceConstructorWithSettersChainInfo.java @@ -73,7 +73,7 @@ public class ReplaceConstructorWithSettersChainInfo extends FixableUsageInfo { "new " + myBuilderClass + "()." + buf.toString() + "create" + StringUtil.capitalize(constructor.getName()) + "()", null); - expr.replace(settersChain); + styleManager.shortenClassReferences(expr.replace(settersChain)); } } } diff --git a/java/java-tests/testData/refactoring/extractMethod/NullableCheckDontMissFinal.java b/java/java-tests/testData/refactoring/extractMethod/NullableCheckDontMissFinal.java new file mode 100644 index 000000000000..f1dea911b29a --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/NullableCheckDontMissFinal.java @@ -0,0 +1,13 @@ +class Test { + void foo() { + final String str = ""; + if (str == "") { + return; + } + new Runnable() { + public void run() { + System.out.println(str); + } + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/NullableCheckDontMissFinal_after.java b/java/java-tests/testData/refactoring/extractMethod/NullableCheckDontMissFinal_after.java new file mode 100644 index 000000000000..47b5fa6686e0 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/NullableCheckDontMissFinal_after.java @@ -0,0 +1,18 @@ +class Test { + void foo() { + final String str = newMethod(); + new Runnable() { + public void run() { + System.out.println(str); + } + } + } + + private String newMethod() { + final String str = ""; + if (str == "") { + return; + } + return str; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/pullUp/PullUpInheritedStaticClasses.java b/java/java-tests/testData/refactoring/pullUp/PullUpInheritedStaticClasses.java new file mode 100644 index 000000000000..48cc5066e1f4 --- /dev/null +++ b/java/java-tests/testData/refactoring/pullUp/PullUpInheritedStaticClasses.java @@ -0,0 +1,8 @@ +public class A extends AA { + + static class C extends D {} + static class D extends B {} + static class B {} +} + +class AA {} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/pullUp/PullUpInheritedStaticClasses_after.java b/java/java-tests/testData/refactoring/pullUp/PullUpInheritedStaticClasses_after.java new file mode 100644 index 000000000000..f11aabb892d3 --- /dev/null +++ b/java/java-tests/testData/refactoring/pullUp/PullUpInheritedStaticClasses_after.java @@ -0,0 +1,10 @@ +public class A extends AA { + + static class B {} +} + +class AA { + static class C extends D {} + + static class D extends A.B {} +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/after/Bar.java b/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/after/Bar.java new file mode 100644 index 000000000000..4722e516f78f --- /dev/null +++ b/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/after/Bar.java @@ -0,0 +1,5 @@ +import foo.Builder; + +public class Bar { + final Test foo = new Builder().setBar("bar").createTest(); +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/after/Test.java b/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/after/Test.java new file mode 100644 index 000000000000..3cc05c40bb7e --- /dev/null +++ b/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/after/Test.java @@ -0,0 +1,7 @@ +public class Test { + private final String bar; + + public Test(final String bar) { + this.bar = bar; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/after/foo/Builder.java b/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/after/foo/Builder.java new file mode 100644 index 000000000000..0887c556595c --- /dev/null +++ b/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/after/foo/Builder.java @@ -0,0 +1,14 @@ +package foo; + +public class Builder { + private String bar; + + public Builder setBar(String bar) { + this.bar = bar; + return this; + } + + public Test createTest() { + return new Test(bar); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/before/Bar.java b/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/before/Bar.java new file mode 100644 index 000000000000..9c0c5a98b8e4 --- /dev/null +++ b/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/before/Bar.java @@ -0,0 +1,3 @@ +public class Bar { + final Test foo = new Test("bar"); +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/before/Test.java b/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/before/Test.java new file mode 100644 index 000000000000..3cc05c40bb7e --- /dev/null +++ b/java/java-tests/testData/refactoring/replaceConstructorWithBuilder/imports/before/Test.java @@ -0,0 +1,7 @@ +public class Test { + private final String bar; + + public Test(final String bar) { + this.bar = bar; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java index 4d95425778a5..1a08474e4d56 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java @@ -400,6 +400,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { doTest(); } + public void testNullableCheckDontMissFinal() throws Exception { + doTest(); + } + public void testSimpleArrayAccess() throws Exception { doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/refactoring/PullUpTest.java b/java/java-tests/testSrc/com/intellij/refactoring/PullUpTest.java index 52149292c41a..d5fe5eedc979 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/PullUpTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/PullUpTest.java @@ -36,6 +36,11 @@ public class PullUpTest extends LightCodeInsightTestCase { new RefactoringTestUtil.MemberDescriptor("setX", PsiMethod.class)); } + + public void testPullUpInheritedStaticClasses() throws Exception { + doTest(new RefactoringTestUtil.MemberDescriptor("C", PsiClass.class), + new RefactoringTestUtil.MemberDescriptor("D", PsiClass.class)); + } public void testPullUpAndAbstractize() throws Exception { doTest(new RefactoringTestUtil.MemberDescriptor("a", PsiMethod.class), diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java index 2643b518c1d1..e6f4d814c019 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java @@ -58,6 +58,10 @@ public class ReplaceConstructorWithBuilderTest extends MultiFileTestCase { doTest(true); } + public void testImports() throws Exception { + doTest(true, null, null, "foo"); + } + private void doTest(final boolean createNewBuilderClass) throws Exception { doTest(createNewBuilderClass, null); } @@ -67,6 +71,13 @@ public class ReplaceConstructorWithBuilderTest extends MultiFileTestCase { } private void doTest(final boolean createNewBuilderClass, final Map expectedDefaults, final String conflicts) throws Exception { + doTest(createNewBuilderClass, expectedDefaults, conflicts, ""); + } + + private void doTest(final boolean createNewBuilderClass, + final Map expectedDefaults, + final String conflicts, + final String packageName) throws Exception { doTest(new PerformAction() { public void performAction(final VirtualFile rootDir, final VirtualFile rootAfter) throws Exception { final PsiClass aClass = myJavaFacade.findClass("Test", GlobalSearchScope.projectScope(getProject())); @@ -85,7 +96,7 @@ public class ReplaceConstructorWithBuilderTest extends MultiFileTestCase { } } try { - new ReplaceConstructorWithBuilderProcessor(getProject(), constructors, map, "Builder", "", createNewBuilderClass).run(); + new ReplaceConstructorWithBuilderProcessor(getProject(), constructors, map, "Builder", packageName, createNewBuilderClass).run(); if (conflicts != null) { fail("Conflicts were not detected:" + conflicts); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java index 55ff32229e95..80f75904567c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java @@ -380,7 +380,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass final Set emptyActionRegistered) { PsiElement psiElement = descriptor.getPsiElement(); if (psiElement == null) return null; - @NonNls String message = renderDescriptionMessage(descriptor); + @NonNls String message = ProblemDescriptionNode.renderDescriptionMessage(descriptor); final HighlightDisplayKey key = HighlightDisplayKey.find(tool.getShortName()); final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); @@ -432,25 +432,6 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass } } - private static String renderDescriptionMessage(ProblemDescriptor descriptor) { - PsiElement psiElement = descriptor.getPsiElement(); - String message = descriptor.getDescriptionTemplate(); - - // no message. Should not be the case if inspection correctly implemented. - // noinspection ConstantConditions - if (message == null) return ""; - - message = StringUtil.replace(message, "", "'"); - message = StringUtil.replace(message, "", "'"); - //message = message.replaceAll("<[^>]*>", ""); - String ref = ProblemDescriptionNode.extractHighlightedText(descriptor, psiElement); - message = StringUtil.replace(message, "#loc", ""); - message = StringUtil.replace(message, "#ref", ref); - - message = StringUtil.unescapeXml(message).trim(); - return message; - } - public static PsiElement[] getElementsIntersectingRange(PsiFile file, final int startOffset, final int endOffset) { final FileViewProvider viewProvider = file.getViewProvider(); final Set result = new LinkedHashSet(); diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/ProblemDescriptionNode.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/ProblemDescriptionNode.java index 24ee0577a4d9..0d09572cecc8 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/ProblemDescriptionNode.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/ProblemDescriptionNode.java @@ -28,7 +28,6 @@ import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FileStatus; import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -44,8 +43,7 @@ public class ProblemDescriptionNode extends InspectionTreeNode { private CommonProblemDescriptor myDescriptor; protected DescriptorProviderInspection myTool; - public ProblemDescriptionNode(final Object userObject, - final DescriptorProviderInspection tool) { + public ProblemDescriptionNode(final Object userObject, final DescriptorProviderInspection tool) { super(userObject); myTool = tool; } @@ -60,9 +58,14 @@ public class ProblemDescriptionNode extends InspectionTreeNode { } @Nullable - public RefEntity getElement() { return myElement; } + public RefEntity getElement() { + return myElement; + } + @Nullable - public CommonProblemDescriptor getDescriptor() { return myDescriptor; } + public CommonProblemDescriptor getDescriptor() { + return myDescriptor; + } public Icon getIcon(boolean expanded) { if (myDescriptor instanceof ProblemDescriptorImpl) { @@ -78,7 +81,7 @@ public class ProblemDescriptionNode extends InspectionTreeNode { } public boolean isValid() { - if (myElement instanceof RefElement && !((RefElement)myElement).isValid()) return false; + if (myElement instanceof RefElement && !myElement.isValid()) return false; final CommonProblemDescriptor descriptor = getDescriptor(); if (descriptor instanceof ProblemDescriptor) { final PsiElement psiElement = ((ProblemDescriptor)descriptor).getPsiElement(); @@ -108,34 +111,50 @@ public class ProblemDescriptionNode extends InspectionTreeNode { } public String toString() { - return renderDescriptionMessage(getDescriptor()); + return renderDescriptionMessage(getDescriptor()).replaceAll("<[^>]*>", ""); } - private static String renderDescriptionMessage(@Nullable CommonProblemDescriptor descriptor) { + public static String renderDescriptionMessage(CommonProblemDescriptor descriptor) { PsiElement psiElement = descriptor instanceof ProblemDescriptor ? ((ProblemDescriptor)descriptor).getPsiElement() : null; - @NonNls String message = descriptor != null ? descriptor.getDescriptionTemplate().replaceAll("<[^>]*>", "") : ""; + String message = descriptor.getDescriptionTemplate(); + + // no message. Should not be the case if inspection correctly implemented. + // noinspection ConstantConditions + if (message == null) return ""; + + message = StringUtil.replace(message, "", "'"); + message = StringUtil.replace(message, "", "'"); message = StringUtil.replace(message, "#loc", ""); - message = StringUtil.replace(message, "#ref", extractHighlightedText(descriptor, psiElement)); + if (message.contains("#ref")) { + String ref = extractHighlightedText(descriptor, psiElement); + message = StringUtil.replace(message, "#ref", ref); + } final int endIndex = message.indexOf("#end"); if (endIndex > 0) { message = message.substring(0, endIndex); } - message = StringUtil.unescapeXml(message); + + message = StringUtil.unescapeXml(message).trim(); return message; } public static String extractHighlightedText(CommonProblemDescriptor descriptor, PsiElement psiElement) { if (psiElement == null || !psiElement.isValid()) return ""; String ref = psiElement.getText(); - if(descriptor instanceof ProblemDescriptorImpl) { + if (descriptor instanceof ProblemDescriptorImpl) { TextRange textRange = ((ProblemDescriptorImpl)descriptor).getTextRange(); final TextRange elementRange = psiElement.getTextRange(); - if (textRange!=null && elementRange!=null) { + if (textRange != null && elementRange != null) { textRange = textRange.shiftRight(-elementRange.getStartOffset()); - if(textRange.getStartOffset() >= 0 && textRange.getEndOffset() <= ref.length()) + if (textRange.getStartOffset() >= 0 && textRange.getEndOffset() <= ref.length()) { ref = textRange.substring(ref); + } } } + ref = ref.replaceAll("\n", " ").trim(); + if (ref.length() > 100) { + ref = ref.substring(0, 100).trim() + "..."; + } return ref; } } diff --git a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java index d07b4c7d2e6e..2b534f422c37 100644 --- a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java +++ b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java @@ -83,11 +83,17 @@ public class ProgramRunnerUtil { public static Icon getConfigurationIcon(final Project project, final RunnerAndConfigurationSettings settings, final boolean invalid) { final RunManager runManager = RunManager.getInstance(project); + return getConfigurationIcon(settings, invalid, runManager.isTemporary(settings.getConfiguration())); + } + + public static Icon getConfigurationIcon(final RunnerAndConfigurationSettings settings, + final boolean invalid, + boolean isTemporary) { RunConfiguration configuration = settings.getConfiguration(); final Icon icon = settings.getFactory().getIcon(configuration); LOG.assertTrue(icon != null, "Icon should not be null!"); - final Icon configurationIcon = runManager.isTemporary(configuration) ? IconLoader.getTransparentIcon(icon, 0.3f) : icon; + final Icon configurationIcon = isTemporary ? IconLoader.getTransparentIcon(icon, 0.3f) : icon; if (invalid) { return LayeredIcon.create(configurationIcon, INVALID_CONFIGURATION); } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java index fa62d357ea01..6f4786b789f2 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java @@ -129,9 +129,9 @@ class RunConfigurable extends BaseConfigurable { catch (ConfigurationException e) { snapshot = settings.getSettings(); } - setIcon(ProgramRunnerUtil.getConfigurationIcon(getProject(), snapshot, !settings.isValid())); configuration = settings.getConfiguration(); name = settings.getNameText(); + setIcon(ProgramRunnerUtil.getConfigurationIcon(snapshot, !settings.isValid(), runManager.isTemporary(configuration))); } else if (userObject instanceof RunnerAndConfigurationSettingsImpl) { RunnerAndConfigurationSettings settings = (RunnerAndConfigurationSettings)userObject; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/TreeElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/TreeElement.java index 40e7a7249221..5d53174fadc4 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/TreeElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/TreeElement.java @@ -93,8 +93,14 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Clonea } public int getStartOffset() { - if (myParent == null) return 0; - return myParent.getStartOffset() + getStartOffsetInParent(); + int result = 0; + TreeElement current = this; + while(current.myParent != null) { + result += current.getStartOffsetInParent(); + current = current.myParent; + } + + return result; } public final int getStartOffsetInParent() { diff --git a/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFilesOrDirectoriesDialog.java b/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFilesOrDirectoriesDialog.java index 4906d0a85439..bd9f6ea921eb 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFilesOrDirectoriesDialog.java +++ b/platform/lang-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/MoveFilesOrDirectoriesDialog.java @@ -19,12 +19,14 @@ package com.intellij.refactoring.move.moveFilesOrDirectories; import com.intellij.ide.util.DirectoryUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.editor.event.DocumentAdapter; -import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; +import com.intellij.openapi.fileChooser.FileChooserFactory; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ComponentWithBrowseButton; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.TextComponentAccessor; import com.intellij.openapi.util.Disposer; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; @@ -32,14 +34,15 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.util.CommonRefactoringUtil; -import com.intellij.ui.EditorComboBox; -import com.intellij.ui.EditorComboWithBrowseButton; +import com.intellij.ui.DocumentAdapter; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.RecentsManager; +import com.intellij.ui.TextFieldWithStoredHistory; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import javax.swing.*; +import javax.swing.event.DocumentEvent; import java.awt.*; import java.io.File; @@ -51,7 +54,7 @@ public class MoveFilesOrDirectoriesDialog extends DialogWrapper{ } private JLabel myNameLabel; - private EditorComboWithBrowseButton myTargetDirectoryField; + private ComponentWithBrowseButton myTargetDirectoryField; private String myHelpID; private final Project myProject; private final Callback myCallback; @@ -89,18 +92,21 @@ public class MoveFilesOrDirectoriesDialog extends DialogWrapper{ panel.add(new JLabel(RefactoringBundle.message("move.files.to.directory.label")), new GridBagConstraints(0,1,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,new Insets(4,8,4,8),0,0)); - myTargetDirectoryField = new EditorComboWithBrowseButton(null, "", myProject, RECENT_KEYS); + myTargetDirectoryField = new ComponentWithBrowseButton(new TextFieldWithStoredHistory(RECENT_KEYS), null); + final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor(); myTargetDirectoryField.addBrowseFolderListener(RefactoringBundle.message("select.target.directory"), RefactoringBundle.message("the.file.will.be.moved.to.this.directory"), myProject, - FileChooserDescriptorFactory.createSingleFolderDescriptor(), - EditorComboBox.COMPONENT_ACCESSOR); + descriptor, + TextComponentAccessor.TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT); + final TextFieldWithStoredHistory textFieldWithStoredHistory = myTargetDirectoryField.getChildComponent(); + FileChooserFactory.getInstance().installFileCompletion(textFieldWithStoredHistory.getTextEditor(), descriptor, true, getDisposable()); myTargetDirectoryField.setTextFieldPreferredWidth(60); panel.add(myTargetDirectoryField, new GridBagConstraints(1,1,1,1,1,0,GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,new Insets(4,0,4,8),0,0)); - myTargetDirectoryField.getChildComponent().getDocument().addDocumentListener(new DocumentAdapter() { + textFieldWithStoredHistory.addDocumentListener(new DocumentAdapter(){ @Override - public void documentChanged(DocumentEvent e) { + protected void textChanged(DocumentEvent e) { validateOKButton(); } }); @@ -135,7 +141,8 @@ public class MoveFilesOrDirectoriesDialog extends DialogWrapper{ RefactoringBundle.message("move.specified.directories") : RefactoringBundle.message("move.specified.elements")); } - myTargetDirectoryField.prependItem(initialTargetDirectory == null ? "" : initialTargetDirectory.getVirtualFile().getPresentableUrl()); + + myTargetDirectoryField.getChildComponent().setText(initialTargetDirectory == null ? "" : initialTargetDirectory.getVirtualFile().getPresentableUrl()); validateOKButton(); myHelpID = helpID; @@ -146,16 +153,16 @@ public class MoveFilesOrDirectoriesDialog extends DialogWrapper{ } private void validateOKButton() { - setOKActionEnabled(myTargetDirectoryField.getText().length() > 0); + setOKActionEnabled(myTargetDirectoryField.getChildComponent().getText().length() > 0); } protected void doOKAction() { - RecentsManager.getInstance(myProject).registerRecentEntry(RECENT_KEYS, myTargetDirectoryField.getText()); + myTargetDirectoryField.getChildComponent().addCurrentTextToHistory(); CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { public void run() { final Runnable action = new Runnable() { public void run() { - String directoryName = myTargetDirectoryField.getText().replace(File.separatorChar, '/'); + String directoryName = myTargetDirectoryField.getChildComponent().getText().replace(File.separatorChar, '/'); try { myTargetDirectory = DirectoryUtil.mkdirs(PsiManager.getInstance(myProject), directoryName); } diff --git a/platform/platform-api/src/com/intellij/lang/Language.java b/platform/platform-api/src/com/intellij/lang/Language.java index c72d3b2c2169..de84644ead03 100644 --- a/platform/platform-api/src/com/intellij/lang/Language.java +++ b/platform/platform-api/src/com/intellij/lang/Language.java @@ -152,7 +152,7 @@ public abstract class Language extends UserDataHolderBase { } public boolean isCaseSensitive() { - return false; + return myBaseLanguage != null ? myBaseLanguage.isCaseSensitive() : false; } public final boolean isKindOf(Language another) { diff --git a/platform/platform-api/src/com/intellij/openapi/ui/TextComponentAccessor.java b/platform/platform-api/src/com/intellij/openapi/ui/TextComponentAccessor.java index 827f978f22f0..510ec59c4ae9 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/TextComponentAccessor.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/TextComponentAccessor.java @@ -16,6 +16,7 @@ package com.intellij.openapi.ui; import com.intellij.ui.TextFieldWithHistory; +import com.intellij.ui.TextFieldWithStoredHistory; import javax.swing.*; import java.awt.*; @@ -82,6 +83,19 @@ public interface TextComponentAccessor { } }; + /** + * The accessor that gets and changes whole text + */ + TextComponentAccessor TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT = new TextComponentAccessor() { + public String getText(TextFieldWithStoredHistory textField) { + return textField.getText(); + } + + public void setText(TextFieldWithStoredHistory textField, String text) { + textField.setText(text); + } + }; + /** * Get text from component * @param component a component to examine diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/LineTooltipRenderer.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/LineTooltipRenderer.java index cb1e903f019e..e6ed3096f99f 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/LineTooltipRenderer.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/LineTooltipRenderer.java @@ -81,14 +81,14 @@ public class LineTooltipRenderer implements TooltipRenderer { int height = expanded ? Math.max(pane.getPreferredSize().height, 150) : pane.getPreferredSize().height; if (alignToRight) { - p.x -= width; + p.x = Math.max(0, p.x - width); } // try to make cursor outside tooltip. SCR 15038 p.x += 3; p.y += 3; - if (p.x + width >= widthLimit) { + if (p.x >= widthLimit - width) { p.x = widthLimit - width; width = Math.min(width, widthLimit); height += 20; @@ -98,7 +98,7 @@ public class LineTooltipRenderer implements TooltipRenderer { p.x = 3; } - if (p.y + height > heightLimit) { + if (p.y > heightLimit - height) { p.y = heightLimit - height; height = Math.min(heightLimit, height); } @@ -107,7 +107,9 @@ public class LineTooltipRenderer implements TooltipRenderer { p.y = 3; } - //in order to restrict tooltip size + locateOutsideMouseCursor(editor, layeredPane, p, width, height, heightLimit); + + // in order to restrict tooltip size pane.setSize(width, height); pane.setMaximumSize(new Dimension(width, height)); pane.setMinimumSize(new Dimension(width, height)); @@ -116,7 +118,6 @@ public class LineTooltipRenderer implements TooltipRenderer { scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - final Ref anAction = new Ref(); final LightweightHint hint = new LightweightHint(scrollPane) { public void hide() { @@ -197,6 +198,27 @@ public class LineTooltipRenderer implements TooltipRenderer { return hint; } + private static void locateOutsideMouseCursor(Editor editor, + JComponent editorComponent, + Point p, + int width, + int height, + int heightLimit) { + Point mouse = MouseInfo.getPointerInfo().getLocation(); + SwingUtilities.convertPointFromScreen(mouse, editorComponent); + Rectangle tooltipRect = new Rectangle(p, new Dimension(width, height)); + // should show at least one line apart + tooltipRect.setBounds(tooltipRect.x, tooltipRect.y - editor.getLineHeight(), width, height + 2 * editor.getLineHeight()); + if (tooltipRect.contains(mouse)) { + if (mouse.y + height + editor.getLineHeight() > heightLimit && mouse.y - height - editor.getLineHeight() > 0) { + p.y = mouse.y - height - editor.getLineHeight(); + } + else { + p.y = mouse.y + editor.getLineHeight(); + } + } + } + protected String convertTextOnLinkHandled(String text) { return text; } diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/TooltipController.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/TooltipController.java index c0e3ea2edebf..82fd73f9ea28 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/TooltipController.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/TooltipController.java @@ -23,6 +23,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.ui.LightweightHint; import com.intellij.ui.awt.RelativePoint; import com.intellij.util.Alarm; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -49,10 +50,11 @@ public class TooltipController { } } - public void showTooltipByMouseMove(final Editor editor, - MouseEvent e, + public void showTooltipByMouseMove(@NotNull final Editor editor, + @NotNull MouseEvent e, final TooltipRenderer tooltipObject, - final boolean alignToRight, final TooltipGroup group) { + final boolean alignToRight, + @NotNull final TooltipGroup group) { myTooltipAlarm.cancelAllRequests(); if (myCurrentTooltip == null || !myCurrentTooltip.isVisible()) { myCurrentTooltipObject = null; @@ -95,11 +97,13 @@ public class TooltipController { } public void showTooltip(final Editor editor, Point p, String text, boolean alignToRight, TooltipGroup group) { - showTooltip(editor, p, ((EditorMarkupModel)editor.getMarkupModel()).getErrorStripTooltipRendererProvider().calcTooltipRenderer(text), alignToRight, group); + TooltipRenderer tooltipRenderer = ((EditorMarkupModel)editor.getMarkupModel()).getErrorStripTooltipRendererProvider().calcTooltipRenderer(text); + showTooltip(editor, p, tooltipRenderer, alignToRight, group); } public void showTooltip(final Editor editor, Point p, String text, int currentWidth, boolean alignToRight, TooltipGroup group) { - showTooltip(editor, p, ((EditorMarkupModel)editor.getMarkupModel()).getErrorStripTooltipRendererProvider().calcTooltipRenderer(text, currentWidth), alignToRight, group); + TooltipRenderer tooltipRenderer = ((EditorMarkupModel)editor.getMarkupModel()).getErrorStripTooltipRendererProvider().calcTooltipRenderer(text, currentWidth); + showTooltip(editor, p, tooltipRenderer, alignToRight, group); } public void showTooltip(final Editor editor, Point p, TooltipRenderer tooltipRenderer, boolean alignToRight, TooltipGroup group) { @@ -133,4 +137,4 @@ public class TooltipController { } return false; } -} \ No newline at end of file +} diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index 50ec133dec53..633e864898d6 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -216,7 +216,7 @@ - +