From 581e899f47debb87838c69d202b09a99e713a1e6 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 21 Apr 2010 16:57:55 +0400 Subject: [PATCH 01/45] exclude method type parameters from extracted class signature (IDEA-53446) --- .../extractclass/ExtractClassProcessor.java | 2 ++ .../methodTypeParameters/after/Extracted.java | 8 ++++++++ .../methodTypeParameters/after/Test.java | 12 ++++++++++++ .../methodTypeParameters/before/Test.java | 10 ++++++++++ .../com/intellij/refactoring/ExtractClassTest.java | 4 ++++ 5 files changed, 36 insertions(+) create mode 100644 java/java-tests/testData/refactoring/extractClass/methodTypeParameters/after/Extracted.java create mode 100644 java/java-tests/testData/refactoring/extractClass/methodTypeParameters/after/Test.java create mode 100644 java/java-tests/testData/refactoring/extractClass/methodTypeParameters/before/Test.java diff --git a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java index e73ea25c55ee..e3eca3742431 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java @@ -110,6 +110,8 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor { } for (PsiMethod method : methods) { method.accept(visitor); + //do not include method's type parameters in class signature + typeParamSet.removeAll(Arrays.asList(method.getTypeParameters())); } typeParams.addAll(typeParamSet); } diff --git a/java/java-tests/testData/refactoring/extractClass/methodTypeParameters/after/Extracted.java b/java/java-tests/testData/refactoring/extractClass/methodTypeParameters/after/Extracted.java new file mode 100644 index 000000000000..bb979dcebb4e --- /dev/null +++ b/java/java-tests/testData/refactoring/extractClass/methodTypeParameters/after/Extracted.java @@ -0,0 +1,8 @@ +public class Extracted { + public Extracted() { + } + + public void foo(T p) { + System.out.println(p.getClass().getName()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractClass/methodTypeParameters/after/Test.java b/java/java-tests/testData/refactoring/extractClass/methodTypeParameters/after/Test.java new file mode 100644 index 000000000000..e4826f85ba8b --- /dev/null +++ b/java/java-tests/testData/refactoring/extractClass/methodTypeParameters/after/Test.java @@ -0,0 +1,12 @@ +class Test { + private final Extracted extracted = new Extracted(); + + public void foo(T p) { + extracted.foo(p); + } + + public static void main(String[] args) { + new Test().foo(10f); + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractClass/methodTypeParameters/before/Test.java b/java/java-tests/testData/refactoring/extractClass/methodTypeParameters/before/Test.java new file mode 100644 index 000000000000..577710ba32f3 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractClass/methodTypeParameters/before/Test.java @@ -0,0 +1,10 @@ +class Test { + public void foo(T p) { + System.out.println(p.getClass().getName()); + } + + public static void main(String[] args) { + new Test().foo(10f); + } + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractClassTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractClassTest.java index 66f5db32490a..f060901f2d58 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractClassTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractClassTest.java @@ -227,6 +227,10 @@ public class ExtractClassTest extends MultiFileTestCase{ doTestField(null); } + public void testMethodTypeParameters() throws Exception { + doTestMethod(); + } + public void testPublicVisibility() throws Exception { doTest(new PerformAction() { public void performAction(final VirtualFile rootDir, final VirtualFile rootAfter) throws Exception { From 73081ee24db66b9bae8c1b76c409f437ab62bfd3 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 21 Apr 2010 20:07:35 +0400 Subject: [PATCH 02/45] package-info.java is involved in Ctrl-Q (IDEA-26014); testdata moved --- .../javadoc/JavaDocInfoGenerator.java | 40 ++++++++++++++----- .../javadocIG/classTypeParameter.html | 3 ++ .../javadocIG/classTypeParameter.java | 6 +++ .../codeInsight/javadocIG/fieldValue.html | 1 + .../codeInsight/javadocIG/fieldValue.java | 4 ++ .../codeInsight/javadocIG/ideadev2326.html | 2 + .../codeInsight/javadocIG/ideadev2326.java | 12 ++++++ .../javadocIG/methodTypeParameter.html | 1 + .../javadocIG/methodTypeParameter.java | 7 ++++ .../javadocIG/packageInfo/package-info.java | 4 ++ .../javadocIG/packageInfo/packageInfo.html | 2 + .../codeInsight/javadocIG/simpleField.html | 1 + .../codeInsight/javadocIG/simpleField.java | 4 ++ .../codeInsight/javadocIG/valueInMethod.html | 1 + .../codeInsight/javadocIG/valueInMethod.java | 6 +++ 15 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/javadocIG/classTypeParameter.html create mode 100644 java/java-tests/testData/codeInsight/javadocIG/classTypeParameter.java create mode 100644 java/java-tests/testData/codeInsight/javadocIG/fieldValue.html create mode 100644 java/java-tests/testData/codeInsight/javadocIG/fieldValue.java create mode 100644 java/java-tests/testData/codeInsight/javadocIG/ideadev2326.html create mode 100644 java/java-tests/testData/codeInsight/javadocIG/ideadev2326.java create mode 100644 java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter.html create mode 100644 java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter.java create mode 100644 java/java-tests/testData/codeInsight/javadocIG/packageInfo/package-info.java create mode 100644 java/java-tests/testData/codeInsight/javadocIG/packageInfo/packageInfo.html create mode 100644 java/java-tests/testData/codeInsight/javadocIG/simpleField.html create mode 100644 java/java-tests/testData/codeInsight/javadocIG/simpleField.java create mode 100644 java/java-tests/testData/codeInsight/javadocIG/valueInMethod.html create mode 100644 java/java-tests/testData/codeInsight/javadocIG/valueInMethod.java diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index 0fff2b07db6c..7453b29a9cb3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.ExternalAnnotationsManager; import com.intellij.codeInsight.documentation.DocumentationManager; +import com.intellij.lang.ASTNode; import com.intellij.lang.LangBundle; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -28,6 +29,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.JavaConstantExpressionEvaluator; +import com.intellij.psi.impl.source.tree.JavaDocElementType; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocTag; import com.intellij.psi.javadoc.PsiDocTagValue; @@ -315,10 +317,7 @@ public class JavaDocInfoGenerator { PsiDocComment comment = getDocComment(aClass); if (comment != null) { - generateDescription(buffer, comment); - generateDeprecatedSection(buffer, comment); - generateSinceSection(buffer, comment); - generateSeeAlsoSection(buffer, comment); + generateCommonSection(buffer, comment); generateTypeParametersSection(buffer, aClass); } generateEpilogue(buffer); @@ -418,10 +417,7 @@ public class JavaDocInfoGenerator { PsiDocComment comment = getDocComment(field); if (comment != null) { - generateDescription(buffer, comment); - generateDeprecatedSection(buffer, comment); - generateSinceSection(buffer, comment); - generateSeeAlsoSection(buffer, comment); + generateCommonSection(buffer, comment); } generateEpilogue(buffer); @@ -463,6 +459,23 @@ public class JavaDocInfoGenerator { private void generatePackageJavaDoc(final StringBuilder buffer, final PsiPackage psiPackage) { for(PsiDirectory directory: psiPackage.getDirectories()) { + final PsiFile packageInfoFile = directory.findFile("package-info.java"); + if (packageInfoFile != null) { + final ASTNode node = packageInfoFile.getNode(); + if (node != null) { + final ASTNode docCommentNode = node.findChildByType(JavaDocElementType.DOC_COMMENT); + if (docCommentNode != null) { + final PsiDocComment docComment = (PsiDocComment)docCommentNode.getPsi(); + + generatePrologue(buffer); + + generateCommonSection(buffer, docComment); + + generateEpilogue(buffer); + break; + } + } + } PsiFile packageHtmlFile = directory.findFile("package.html"); if (packageHtmlFile != null) { generatePackageHtmlJavaDoc(buffer, packageHtmlFile); @@ -471,6 +484,13 @@ public class JavaDocInfoGenerator { } } + private void generateCommonSection(StringBuilder buffer, PsiDocComment docComment) { + generateDescription(buffer, docComment); + generateDeprecatedSection(buffer, docComment); + generateSinceSection(buffer, docComment); + generateSeeAlsoSection(buffer, docComment); + } + private void generatePackageHtmlJavaDoc(final StringBuilder buffer, final PsiFile packageHtmlFile) { String htmlText; XmlFile packageXmlFile = (XmlFile) packageHtmlFile; @@ -502,9 +522,7 @@ public class JavaDocInfoGenerator { generatePrologue(buffer); - generateDescription(buffer, docComment); - generateSinceSection(buffer, docComment); - generateSeeAlsoSection(buffer, docComment); + generateCommonSection(buffer, docComment); generateEpilogue(buffer); } diff --git a/java/java-tests/testData/codeInsight/javadocIG/classTypeParameter.html b/java/java-tests/testData/codeInsight/javadocIG/classTypeParameter.html new file mode 100644 index 000000000000..531cb6123a81 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/classTypeParameter.html @@ -0,0 +1,3 @@ +
class MethodTypeParam<T>
+extends Object
+
Type parameters:
<T> - type param
\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/classTypeParameter.java b/java/java-tests/testData/codeInsight/javadocIG/classTypeParameter.java new file mode 100644 index 000000000000..1ceb9caa5398 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/classTypeParameter.java @@ -0,0 +1,6 @@ +/** + * @param type param + */ +class MethodTypeParam { + +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/fieldValue.html b/java/java-tests/testData/codeInsight/javadocIG/fieldValue.html new file mode 100644 index 000000000000..6f269de54369 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/fieldValue.html @@ -0,0 +1 @@ + A
public static int JAVADOC_ME = 23
The value of the field is 23. \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/fieldValue.java b/java/java-tests/testData/codeInsight/javadocIG/fieldValue.java new file mode 100644 index 000000000000..01c0ff6936cb --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/fieldValue.java @@ -0,0 +1,4 @@ +class A { + /** The value of the field is {@value}. */ + public static int JAVADOC_ME = 23; +} diff --git a/java/java-tests/testData/codeInsight/javadocIG/ideadev2326.html b/java/java-tests/testData/codeInsight/javadocIG/ideadev2326.html new file mode 100644 index 000000000000..4ada6b3a0ac8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/ideadev2326.html @@ -0,0 +1,2 @@ + Idea4780
public Object read()
+           throws IOException
Throws:
EOFException - if this source is already closed when the read() is called, or is closed during the read().
InterruptedIOException - if the reading thread is interrupted.
IOException - if an I/O error occurs while reading.
\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/ideadev2326.java b/java/java-tests/testData/codeInsight/javadocIG/ideadev2326.java new file mode 100644 index 000000000000..ba8b065e36f8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/ideadev2326.java @@ -0,0 +1,12 @@ +import java.io.*; + +public interface Idea4780 { + /** + * @throws IOException if an I/O error occurs while reading. + * @throws EOFException if this source is already closed when the read() is called, + * or is closed during the read(). + * @throws InterruptedIOException if the reading thread is interrupted. + */ + public Object read() + throws IOException; +} diff --git a/java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter.html b/java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter.html new file mode 100644 index 000000000000..1d324319ab10 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter.html @@ -0,0 +1 @@ + MethodTypeParam
<T> void foo(T t)
Type parameters:
<T> - type param
\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter.java b/java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter.java new file mode 100644 index 000000000000..5ad5d851af69 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/methodTypeParameter.java @@ -0,0 +1,7 @@ +class MethodTypeParam { + /** + * @param type param + */ + void foo(T t) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/packageInfo/package-info.java b/java/java-tests/testData/codeInsight/javadocIG/packageInfo/package-info.java new file mode 100644 index 000000000000..5dc3f1b97914 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/packageInfo/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains nothing but package-info.java + */ +package packageInfo; \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/packageInfo/packageInfo.html b/java/java-tests/testData/codeInsight/javadocIG/packageInfo/packageInfo.html new file mode 100644 index 000000000000..a258c8654e7a --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/packageInfo/packageInfo.html @@ -0,0 +1,2 @@ + + This package contains nothing but package-info.java \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/simpleField.html b/java/java-tests/testData/codeInsight/javadocIG/simpleField.html new file mode 100644 index 000000000000..ddbd3871a41f --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/simpleField.html @@ -0,0 +1 @@ + A
public static int JAVADOC_ME
Test \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/simpleField.java b/java/java-tests/testData/codeInsight/javadocIG/simpleField.java new file mode 100644 index 000000000000..1172e6919bf1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/simpleField.java @@ -0,0 +1,4 @@ +class A { + /** Test */ + public static int JAVADOC_ME; +} diff --git a/java/java-tests/testData/codeInsight/javadocIG/valueInMethod.html b/java/java-tests/testData/codeInsight/javadocIG/valueInMethod.html new file mode 100644 index 000000000000..91b1c9744ed7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/valueInMethod.html @@ -0,0 +1 @@ + A
public static void JAVADOC_ME()
The value of A is 23. \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/valueInMethod.java b/java/java-tests/testData/codeInsight/javadocIG/valueInMethod.java new file mode 100644 index 000000000000..4c7e205db70e --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/valueInMethod.java @@ -0,0 +1,6 @@ +class A { + public static int A = 23; + + /** The value of A is {@value #A}. */ + public static void JAVADOC_ME() { } +} From cfd764a9c90fd3ae75e23b1c922b568296c788d7 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 21 Apr 2010 20:46:24 +0400 Subject: [PATCH 03/45] suggest to rename tests if corresponding class was renamed ( IDEA-19812 ) --- .../refactoring/JavaRefactoringSettings.java | 9 ++ .../naming/AutomaticTestRenamerFactory.java | 83 +++++++++++++++++++ .../src/messages/RefactoringBundle.properties | 4 + resources/src/META-INF/IdeaPlugin.xml | 1 + 4 files changed, 97 insertions(+) create mode 100644 java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticTestRenamerFactory.java diff --git a/java/java-impl/src/com/intellij/refactoring/JavaRefactoringSettings.java b/java/java-impl/src/com/intellij/refactoring/JavaRefactoringSettings.java index f61f70cffb99..bcb261bdb727 100644 --- a/java/java-impl/src/com/intellij/refactoring/JavaRefactoringSettings.java +++ b/java/java-impl/src/com/intellij/refactoring/JavaRefactoringSettings.java @@ -100,6 +100,7 @@ public class JavaRefactoringSettings implements PersistentStateComponent usages) { + return new TestsRenamer((PsiClass)element, newName); + } + + private static class TestsRenamer extends AutomaticRenamer { + public TestsRenamer(PsiClass aClass, String newClassName) { + + appendTestClass(aClass, "Test"); + appendTestClass(aClass, "TestCase"); + + suggestAllNames(aClass.getName(), newClassName); + } + + private void appendTestClass(PsiClass aClass, String testSuffix) { + final Project project = aClass.getProject(); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + final PsiClass psiClassTest = facade.findClass(aClass.getQualifiedName() + testSuffix, GlobalSearchScope.projectScope(project)); + if (psiClassTest != null) { + myElements.add(psiClassTest); + } + } + + public String getDialogTitle() { + return RefactoringBundle.message("rename.tests.title"); + } + + public String getDialogDescription() { + return RefactoringBundle.message("rename.tests.with.the.following.names.to"); + } + + public String entityName() { + return RefactoringBundle.message("entity.name.test"); + } + } +} diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties index 909d679b0513..97799609dd07 100644 --- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties +++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties @@ -562,6 +562,7 @@ automatic.renamer.rename.to.column=Rename To rename.0.and.its.usages.to=Rename {0} and its usages to: rename.variables=Rename &variables rename.inheritors=Rename &inheritors +rename.tests=Rename &tests rename.parameters.hierarchy=Rename parameters in hier&archy rename.bound.forms=Rename bound &forms inner.class.0.is.already.defined.in.class.1=Inner class {0} is already defined in class {1}.\nContinue anyway? @@ -577,8 +578,11 @@ rename.bound.forms.title=Rename bound forms rename.forms.with.the.following.names.to=Rename forms with the following names to: entity.name.form=Form rename.inheritors.title=Rename Inheritors +rename.tests.title=Rename Tests rename.inheritors.with.the.following.names.to=Rename inheritors with the following names to: +rename.tests.with.the.following.names.to=Rename tests with the following names to: entity.name.inheritor=Inheritor +entity.name.test=Test unused.overriding.methods.title=Unused Overriding Methods there.are.unused.methods.that.override.methods.you.delete=There are unused methods that override methods you delete. choose.the.ones.you.want.to.be.deleted=Choose the ones you want to be deleted. diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 1f88249aa728..a32a3ec171c9 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -1016,6 +1016,7 @@ + From bb3cacc36cf45d2ed25ccb5f4e9c00644aff4d40 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 21 Apr 2010 21:04:29 +0400 Subject: [PATCH 04/45] allow to change constructor signature when caret is on constructor call --- .../changeSignature/ChangeSignatureTargetUtil.java | 5 +++-- .../refactoring/changeSignatureTarget/inTypeArguments.java | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureTargetUtil.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureTargetUtil.java index 5c947f4c48bb..b4735a329f85 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureTargetUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureTargetUtil.java @@ -35,10 +35,11 @@ public class ChangeSignatureTargetUtil { return PsiTreeUtil.getParentOfType(element, PsiMethod.class); } - final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class); + final PsiCallExpression expression = PsiTreeUtil.getParentOfType(element, PsiCallExpression.class); if (expression != null) { assert element != null; - final PsiExpression qualifierExpression = expression.getMethodExpression().getQualifierExpression(); + final PsiExpression qualifierExpression = expression instanceof PsiMethodCallExpression ? ((PsiMethodCallExpression)expression).getMethodExpression().getQualifierExpression() + : expression instanceof PsiNewExpression ? ((PsiNewExpression)expression).getQualifier() : null; if (PsiTreeUtil.isAncestor(qualifierExpression, element, false)) { final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(qualifierExpression, PsiExpressionList.class); if (expressionList != null) { diff --git a/java/java-tests/testData/refactoring/changeSignatureTarget/inTypeArguments.java b/java/java-tests/testData/refactoring/changeSignatureTarget/inTypeArguments.java index d0fb0a13392e..088e9bbcc97d 100644 --- a/java/java-tests/testData/refactoring/changeSignatureTarget/inTypeArguments.java +++ b/java/java-tests/testData/refactoring/changeSignatureTarget/inTypeArguments.java @@ -1,5 +1,7 @@ import java.util.*; class A1 { + A1(){} + public static void main(String[] args) { Callable callable = new Callable() { From ff63d5e3e3548e7792b3c8f5c2b04cc76191c686 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 21 Apr 2010 21:18:59 +0400 Subject: [PATCH 05/45] enable wrong package statement for package-info.java files ( IDEA-53604 ) --- .../WrongPackageStatementInspection.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspection.java b/java/java-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspection.java index 04365a22fbf6..560f2f11f13a 100644 --- a/java/java-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspection.java @@ -40,15 +40,17 @@ public class WrongPackageStatementInspection extends BaseJavaLocalInspectionTool if (file instanceof PsiJavaFile) { if (JspPsiUtil.isInJspFile(file)) return null; PsiJavaFile javaFile = (PsiJavaFile)file; - // highlight the first class in the file only - PsiClass[] classes = javaFile.getClasses(); - if (classes.length == 0) return null; + PsiDirectory directory = javaFile.getContainingDirectory(); if (directory == null) return null; PsiPackage dirPackage = JavaDirectoryService.getInstance().getPackage(directory); if (dirPackage == null) return null; PsiPackageStatement packageStatement = javaFile.getPackageStatement(); + // highlight the first class in the file only + PsiClass[] classes = javaFile.getClasses(); + if (classes.length == 0 && packageStatement == null) return null; + String packageName = dirPackage.getQualifiedName(); if (!Comparing.strEqual(packageName, "", true) && packageStatement == null) { String description = JavaErrorMessages.message("missing.package.statement", packageName); @@ -75,7 +77,7 @@ public class WrongPackageStatementInspection extends BaseJavaLocalInspectionTool String description = JavaErrorMessages.message("package.name.file.path.mismatch", packageReference.getText(), dirPackage.getQualifiedName()); - return new ProblemDescriptor[]{manager.createProblemDescriptor(packageStatement, description, isOnTheFly, availableFixes.toArray(new LocalQuickFix[availableFixes.size()]), ProblemHighlightType.GENERIC_ERROR_OR_WARNING)}; + return new ProblemDescriptor[]{manager.createProblemDescriptor(packageStatement.getPackageReference(), description, isOnTheFly, availableFixes.toArray(new LocalQuickFix[availableFixes.size()]), ProblemHighlightType.GENERIC_ERROR_OR_WARNING)}; } } From 6a72485e0d227423e2321a3d1ff657ba0e3254e4 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 22 Apr 2010 14:38:43 +0400 Subject: [PATCH 06/45] IDEA-54248 Error when indexing a package called xml --- .../testng/src/com/theoryinpractice/testng/util/TestNGUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/testng/src/com/theoryinpractice/testng/util/TestNGUtil.java b/plugins/testng/src/com/theoryinpractice/testng/util/TestNGUtil.java index 02570512b051..ec396fd77e7c 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/util/TestNGUtil.java +++ b/plugins/testng/src/com/theoryinpractice/testng/util/TestNGUtil.java @@ -553,7 +553,7 @@ public class TestNGUtil implements TestFramework } public static boolean isTestngXML(final VirtualFile virtualFile) { - if (virtualFile.getName().endsWith("xml")) { + if ("xml".equalsIgnoreCase(virtualFile.getExtension())) { final String result = NanoXmlUtil.parseHeader(virtualFile).getRootTagLocalName(); if (result != null && result.equals(SUITE_TAG_NAME)) { return true; From b1ca0f5b484f4b37d684e02b1c0dc2e51fa16686 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 21 Apr 2010 20:33:58 +0400 Subject: [PATCH 07/45] LH: assertions --- .../com/intellij/history/core/storage/StreamUtil.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/platform/lvcs-impl/src/com/intellij/history/core/storage/StreamUtil.java b/platform/lvcs-impl/src/com/intellij/history/core/storage/StreamUtil.java index fc065965bbbc..503f718cf18a 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/storage/StreamUtil.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/storage/StreamUtil.java @@ -52,8 +52,8 @@ public class StreamUtil { } public static Change readChange(DataInput in) throws IOException { - switch (in.readInt()) { - case 0: + int type = in.readInt(); + switch (type) { case 1: return new CreateFileChange(in); case 2: @@ -73,14 +73,13 @@ public class StreamUtil { case 9: return new PutSystemLabelChange(in); } - throw new IOException(); + throw new IOException("unexpected change type: " + type); } public static void writeChange(DataOutput out, Change change) throws IOException { int id = -1; Class c = change.getClass(); - if (c.equals(ChangeSet.class)) id = 0; if (c.equals(CreateFileChange.class)) id = 1; if (c.equals(CreateDirectoryChange.class)) id = 2; if (c.equals(ContentChange.class)) id = 3; @@ -91,7 +90,7 @@ public class StreamUtil { if (c.equals(PutLabelChange.class)) id = 8; if (c.equals(PutSystemLabelChange.class)) id = 9; - assert id != -1; + if (id == -1) throw new IOException("unexpected change type: " + c); out.writeInt(id); change.write(out); From cf777e15bc2cdada7eea5eb5c40a7df1c6d96caf Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 22 Apr 2010 14:41:44 +0400 Subject: [PATCH 08/45] LH: storage bug fix --- .../com/intellij/history/core/ChangeList.java | 2 +- .../history/core/ChangeListStorageImpl.java | 6 +- .../history/core/LinkedRecordsTable.java | 11 +- .../intellij/history/core/LinkedStorage.java | 12 ++ .../historyIntegrTests/LinkedStorageTest.java | 147 ++++++++++++++++++ .../util/io/storage/AbstractRecordsTable.java | 3 + .../util/io/storage/RecordsTable.java | 4 + .../io/storage/RefCountingRecordsTable.java | 5 + 8 files changed, 182 insertions(+), 8 deletions(-) create mode 100644 platform/lvcs-impl/testSrc/com/intellij/historyIntegrTests/LinkedStorageTest.java diff --git a/platform/lvcs-impl/src/com/intellij/history/core/ChangeList.java b/platform/lvcs-impl/src/com/intellij/history/core/ChangeList.java index 3fc8641a09f6..f180a35105ee 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/ChangeList.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/ChangeList.java @@ -144,7 +144,7 @@ public class ChangeList { } private void flushChanges(boolean force) { - if (myChangeSetDepth > 0) return; + if (myChangeSetDepth > 0) return; if (myCurrentBlock.shouldFlush(force) || flushEveryChangeSetInTests()) { myStorage.writeNextBlock(myCurrentBlock); myCurrentBlock = myStorage.createNewBlock(); diff --git a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java index 3b9a32962074..5c5159e2aae0 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java @@ -140,7 +140,7 @@ public class ChangeListStorageImpl implements ChangeListStorage { } public synchronized List purge(long period, int intervalBetweenActivities) { - List result = new ArrayList(); + List result = new ArrayList(); // todo : do not collect changesets int each = findFirstObsoleteBlock(period, intervalBetweenActivities); try { while(each != 0) { @@ -155,7 +155,6 @@ public class ChangeListStorageImpl implements ChangeListStorage { return result; } - private int findFirstObsoleteBlock(long period, int intervalBetweenActivities) { long prevTimestamp = 0; long length = 0; @@ -178,8 +177,7 @@ public class ChangeListStorageImpl implements ChangeListStorage { return 0; } - - public void flush() { + public synchronized void flush() { myStorage.flushSome(); } } \ No newline at end of file diff --git a/platform/lvcs-impl/src/com/intellij/history/core/LinkedRecordsTable.java b/platform/lvcs-impl/src/com/intellij/history/core/LinkedRecordsTable.java index 5a40317b5a92..a49a7fd24b5d 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/LinkedRecordsTable.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/LinkedRecordsTable.java @@ -23,7 +23,7 @@ import java.io.File; import java.io.IOException; public class LinkedRecordsTable extends AbstractRecordsTable { - private static final int VERSION = 3; + private static final int VERSION = 4; private static final int ID_COUNTER_OFFSET = DEFAULT_HEADER_SIZE; private static final int FIRST_RECORD_OFFSET = ID_COUNTER_OFFSET + 8; @@ -62,6 +62,13 @@ public class LinkedRecordsTable extends AbstractRecordsTable { return ZEROS; } + @Override + protected void clearDeletedRecord(int record) { + setTimestamp(record, 0); + setNextRecord(record, 0); + setPrevRecord(record, 0); + } + public void setFSTimestamp(long timestamp) { markDirty(); myStorage.putLong(FS_TIMESTAMP_OFFSET, timestamp); @@ -77,7 +84,6 @@ public class LinkedRecordsTable extends AbstractRecordsTable { } public int getFirstRecord() { - markDirty(); return myStorage.getInt(FIRST_RECORD_OFFSET); } @@ -87,7 +93,6 @@ public class LinkedRecordsTable extends AbstractRecordsTable { } public int getLastRecord() { - markDirty(); return myStorage.getInt(LAST_RECORD_OFFSET); } diff --git a/platform/lvcs-impl/src/com/intellij/history/core/LinkedStorage.java b/platform/lvcs-impl/src/com/intellij/history/core/LinkedStorage.java index cbabb7082ddb..b4d3aa8f3de3 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/LinkedStorage.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/LinkedStorage.java @@ -55,6 +55,12 @@ public class LinkedStorage extends AbstractStorage { } } + public int getFirstRecord() { + synchronized (myLock) { + return ((LinkedRecordsTable)myRecordsTable).getFirstRecord(); + } + } + public int getLastRecord() { synchronized (myLock) { return ((LinkedRecordsTable)myRecordsTable).getLastRecord(); @@ -67,6 +73,12 @@ public class LinkedStorage extends AbstractStorage { } } + public int getNextRecord(int record) { + synchronized (myLock) { + return ((LinkedRecordsTable)myRecordsTable).getNextRecord(record); + } + } + public long getTimestamp(int record) { synchronized (myLock) { return ((LinkedRecordsTable)myRecordsTable).getTimestamp(record); diff --git a/platform/lvcs-impl/testSrc/com/intellij/historyIntegrTests/LinkedStorageTest.java b/platform/lvcs-impl/testSrc/com/intellij/historyIntegrTests/LinkedStorageTest.java new file mode 100644 index 000000000000..a3d058d32663 --- /dev/null +++ b/platform/lvcs-impl/testSrc/com/intellij/historyIntegrTests/LinkedStorageTest.java @@ -0,0 +1,147 @@ +/* + * Copyright 2000-2010 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.historyIntegrTests; + +import com.intellij.history.core.LinkedStorage; +import com.intellij.util.io.storage.AbstractStorage; + +import java.io.DataInputStream; +import java.io.IOException; + +public class LinkedStorageTest extends IntegrationTestCase { + private LinkedStorage myStorage; + + @Override + public void setUp() throws Exception { + super.setUp(); + myStorage = new LinkedStorage(myRoot.getPath() + "/storage"); + } + + @Override + protected void tearDown() throws Exception { + myStorage.dispose(); + super.tearDown(); + } + + public void testBasic() throws Exception { + assertFirstAndLast(0, 0); + + int r1 = createRecord(); + int r2 = createRecord(); + + assertFirstAndLast(r1, r2); + assertRecord(r2, r1, 0); + assertRecord(r1, 0, r2); + } + + public void testDeletion() throws Exception { + int r1 = createRecord(); + int r2 = createRecord(); + int r3 = createRecord(); + + assertFirstAndLast(r1, r3); + assertRecord(r3, r2, 0); + assertRecord(r2, r1, r3); + assertRecord(r1, 0, r2); + + myStorage.deleteRecord(r2); + + assertFirstAndLast(r1, r3); + assertRecord(r3, r1, 0); + assertRecord(r1, 0, r3); + + myStorage.deleteRecord(r3); + + assertFirstAndLast(r1, r1); + assertRecord(r1, 0, 0); + + int r4 = createRecord(); + + assertFirstAndLast(r1, r4); + assertRecord(r4, r1, 0); + assertRecord(r1, 0, r4); + + myStorage.deleteRecord(r1); + + assertFirstAndLast(r4, r4); + assertRecord(r4, 0, 0); + + myStorage.deleteRecord(r4); + + assertFirstAndLast(0, 0); + } + + public void testReopening() throws Exception { + int r1 = createRecord(); + int r2 = createRecord(); + int r3 = createRecord(); + + myStorage.deleteRecord(r2); + + myStorage.dispose(); + myStorage = new LinkedStorage(myRoot.getPath() + "/storage"); + + assertFirstAndLast(r1, r3); + assertRecord(r3, r1, 0); + assertRecord(r1, 0, r3); + + myStorage.deleteRecord(r1); + + myStorage.dispose(); + myStorage = new LinkedStorage(myRoot.getPath() + "/storage"); + + assertFirstAndLast(r3, r3); + assertRecord(r3, 0, 0); + + int r4 = createRecord(); + + myStorage.dispose(); + myStorage = new LinkedStorage(myRoot.getPath() + "/storage"); + + assertFirstAndLast(r3, r4); + assertRecord(r4, r3, 0); + assertRecord(r3, 0, r4); + } + + private int createRecord() throws IOException { + int r = myStorage.createNextRecord(); + AbstractStorage.StorageDataOutput s = myStorage.writeStream(r); + for (int i = 0; i < 1000; i++) { + s.writeInt(r); + } + s.close(); + return r; + } + + private void assertFirstAndLast(int first, int last) { + assertEquals(first, myStorage.getFirstRecord()); + assertEquals(last, myStorage.getLastRecord()); + } + + private void assertRecord(int id, int prev, int next) throws IOException { + assertEquals(prev, myStorage.getPrevRecord(id)); + assertEquals(next, myStorage.getNextRecord(id)); + DataInputStream s = myStorage.readStream(id); + try { + for (int i = 0; i < 1000; i++) { + assertEquals(id, s.readInt()); + } + } + finally { + s.close(); + } + } +} diff --git a/platform/util/src/com/intellij/util/io/storage/AbstractRecordsTable.java b/platform/util/src/com/intellij/util/io/storage/AbstractRecordsTable.java index 04cac6518ffb..c02628e4030e 100644 --- a/platform/util/src/com/intellij/util/io/storage/AbstractRecordsTable.java +++ b/platform/util/src/com/intellij/util/io/storage/AbstractRecordsTable.java @@ -173,9 +173,12 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable { public void deleteRecord(final int record) { ensureFreeRecordsScanned(); setSize(record, -1); + clearDeletedRecord(record); myFreeRecordsList.add(record); } + protected abstract void clearDeletedRecord(int record); + public int getVersion() { return myStorage.getInt(HEADER_VERSION_OFFSET); } diff --git a/platform/util/src/com/intellij/util/io/storage/RecordsTable.java b/platform/util/src/com/intellij/util/io/storage/RecordsTable.java index 3e53a9c4c1f2..0c6243937edc 100644 --- a/platform/util/src/com/intellij/util/io/storage/RecordsTable.java +++ b/platform/util/src/com/intellij/util/io/storage/RecordsTable.java @@ -47,4 +47,8 @@ class RecordsTable extends AbstractRecordsTable { protected byte[] getZeros() { return ZEROES; } + + @Override + protected void clearDeletedRecord(int record) { + } } diff --git a/platform/util/src/com/intellij/util/io/storage/RefCountingRecordsTable.java b/platform/util/src/com/intellij/util/io/storage/RefCountingRecordsTable.java index 025dc80e6d00..0b3bb50012a0 100644 --- a/platform/util/src/com/intellij/util/io/storage/RefCountingRecordsTable.java +++ b/platform/util/src/com/intellij/util/io/storage/RefCountingRecordsTable.java @@ -47,6 +47,11 @@ class RefCountingRecordsTable extends AbstractRecordsTable { return ZEROES; } + @Override + protected void clearDeletedRecord(int record) { + myStorage.putInt(getOffset(record, REF_COUNT_OFFSET), 0); + } + public void incRefCount(int record) { markDirty(); From 8e1b726f049e31d01839a5fc665deaf83a0ff1a5 Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Thu, 22 Apr 2010 14:49:31 +0400 Subject: [PATCH 09/45] logging for project reloading on external changes --- .../intellij/openapi/project/impl/ProjectManagerImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index a1c0f774aeae..d71326a9e1c5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -110,6 +110,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt connection.subscribe(StateStorage.STORAGE_TOPIC, new StateStorage.Listener() { public void storageFileChanged(final VirtualFileEvent event, @NotNull final StateStorage storage) { VirtualFile file = event.getFile(); + LOG.info("[RELOAD] Storage file changed: " + file.getPath()); if (!file.isDirectory() && !(event.getRequestor() instanceof StateStorage.SaveSession)) { saveChangedProjectFile(file, null, storage); } @@ -535,6 +536,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } private void askToReloadProjectIfConfigFilesChangedExternally() { + LOG.info("[RELOAD] myReloadBlockCount = " + myReloadBlockCount.get()); if (myReloadBlockCount.get() == 0) { Set projects; @@ -572,7 +574,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { try { - reloadOk[0] = ((ApplicationImpl)app).getStateStore().reload(causes, components); } catch (StateStorage.StateStorageException e) { @@ -639,6 +640,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { try { + LOG.info("[RELOAD] Reloading project/components..."); reloadOk[0] = ((ProjectEx)project).getStateStore().reload(causes); } catch (StateStorage.StateStorageException e) { @@ -725,6 +727,8 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } private void registerProjectToReload(final Project project, final VirtualFile cause, final StateStorage storage) { + LOG.info("[RELOAD] Registering project to reload."); + if (project != null) { synchronized (myChangedProjectFiles) { List> changedProjectFiles = myChangedProjectFiles.get(project); @@ -743,6 +747,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt myChangedFilesAlarm.cancelAllRequests(); myChangedFilesAlarm.addRequest(new Runnable() { public void run() { + LOG.info("[RELOAD] Scheduling reload application & project, myReloadBlockCount = " + myReloadBlockCount); if (myReloadBlockCount.get() == 0) { scheduleReloadApplicationAndProject(); } From 68640d5efb4032af9637e2f7074fc40499c10318 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 22 Apr 2010 15:39:07 +0400 Subject: [PATCH 10/45] LH: directory history dialog UI improved --- .../history/integration/ui/views/DirectoryHistoryDialog.java | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/DirectoryHistoryDialog.java b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/DirectoryHistoryDialog.java index aa5d3ab4007d..51bbfe1152ed 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/DirectoryHistoryDialog.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/DirectoryHistoryDialog.java @@ -81,7 +81,6 @@ public class DirectoryHistoryDialog extends HistoryDialog Date: Thu, 22 Apr 2010 16:11:01 +0400 Subject: [PATCH 11/45] IDEA-43962 Indentation error on deep nesting levels 1. Typo is corrected; 2. Meaningful toString() is defined in order to make more convenient debugging of all sub-classes; 3. Green code policy is applied; --- .../formatting/AbstractBlockWrapper.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java index ca1a4ac5bbe1..4a6afb5f9c23 100644 --- a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java +++ b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java @@ -125,7 +125,7 @@ public abstract class AbstractBlockWrapper { } /** - * Calculates indent for the given block and target start offset according to the given idnent options. + * Calculates indent for the given block and target start offset according to the given indent options. * * @param options indent options to use * @param block target wrapped block @@ -255,18 +255,13 @@ public abstract class AbstractBlockWrapper { return indent.add(getWhiteSpace()); } else { - ArrayList ignored = new ArrayList(); IndentData offsetFromParent = myParent.getChildOffset(this, indentOption, -1); - IndentData result = indent.add(offsetFromParent); - if (!ignored.isEmpty()) { - result = result.add(ignored.get(ignored.size() - 1)); - } - return result; + return indent.add(offsetFromParent); } } - private IndentData getIndent(final CodeStyleSettings.IndentOptions options, final int index, IndentImpl indent) { + private static IndentData getIndent(final CodeStyleSettings.IndentOptions options, final int index, IndentImpl indent) { if (indent.getType() == IndentImpl.Type.CONTINUATION) { return new IndentData(options.CONTINUATION_INDENT_SIZE); } @@ -292,7 +287,7 @@ public abstract class AbstractBlockWrapper { * value is defined (not null). *

* This property is used later during - * {@link LeafBlockWrapper#calculateOffset(CodeStyleSettings.IndentOptions) leaf block offset calculation}. + * {@link LeafBlockWrapper#calculateOffset(CodeStyleSettings.IndentOptions)} leaf block offset calculation}. * * @param indentFromParent indent value to apply */ @@ -340,4 +335,9 @@ public abstract class AbstractBlockWrapper { myParent = null; myWhiteSpace = null; } + + @Override + public String toString() { + return getClass().getName() + "(" + myStart + "-" + myEnd + ")"; + } } From b386b68985ce4d2a39ebedf64faec47790a5b0d8 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:18:26 +0400 Subject: [PATCH 12/45] IDEA-43962 Indentation error on deep nesting levels 1. Big chunk of wrap-processing logic is moved to JavaWrapManager; 2. Meaningful name is given to processParenthesisBlock() method (make spell checker inspection happy); 3. Building of blocks inside parenthesis is delegated to processChild() because method calls inside expression list were processed incorrectly and we don't to duplicate that processing logic; 4. Adopted to ReservedWrapsProvider interface; --- .../psi/formatter/java/AbstractJavaBlock.java | 315 ++++-------------- 1 file changed, 56 insertions(+), 259 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java index d040a3128952..d81d710a97ce 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java @@ -24,6 +24,8 @@ import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.formatter.common.AbstractBlock; import com.intellij.psi.formatter.common.JavaBlockUtil; +import com.intellij.psi.formatter.java.wrap.JavaWrapManager; +import com.intellij.psi.formatter.java.wrap.ReservedWrapsProvider; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.impl.source.tree.java.ClassElement; @@ -37,7 +39,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlock { +public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlock, ReservedWrapsProvider { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.formatter.java.AbstractJavaBlock"); protected final CodeStyleSettings mySettings; @@ -51,16 +53,21 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo protected Alignment myReservedAlignment; protected Alignment myReservedAlignment2; - + private final JavaWrapManager myWrapManager; - protected AbstractJavaBlock(final ASTNode node, - final Wrap wrap, - final Alignment alignment, - final Indent indent, - final CodeStyleSettings settings) { + protected AbstractJavaBlock(final ASTNode node, final Wrap wrap, final Alignment alignment, final Indent indent, + final CodeStyleSettings settings) + { + this(node, wrap, alignment, indent, settings, JavaWrapManager.INSTANCE); + } + + protected AbstractJavaBlock(final ASTNode node, final Wrap wrap, final Alignment alignment, final Indent indent, + final CodeStyleSettings settings, JavaWrapManager wrapManager) + { super(node, wrap, alignment); mySettings = settings; myIndent = indent; + myWrapManager = wrapManager; } public static Block createJavaBlock(final ASTNode child, @@ -159,7 +166,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } } - final ASTNode prevElement = getPrevElement(child); + final ASTNode prevElement = FormattingAstUtil.getPrevElement(child); if (prevElement != null && prevElement.getElementType() == JavaElementType.MODIFIER_LIST) { return Indent.getNoneIndent(); } @@ -234,51 +241,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo @Nullable protected Wrap createChildWrap() { - final IElementType nodeType = myNode.getElementType(); - if (nodeType == JavaElementType.EXTENDS_LIST || nodeType == JavaElementType.IMPLEMENTS_LIST) { - return Wrap.createWrap(getWrapType(mySettings.EXTENDS_LIST_WRAP), false); - } - else if (nodeType == JavaElementType.BINARY_EXPRESSION) { - Wrap actualWrap = myWrap != null ? myWrap : getReservedWrap(JavaElementType.BINARY_EXPRESSION); - if (actualWrap == null) { - return Wrap.createWrap(getWrapType(mySettings.BINARY_OPERATION_WRAP), false); - } - else { - if (!hasTheSamePriority(myNode.getTreeParent())) { - return Wrap.createChildWrap(actualWrap, getWrapType(mySettings.BINARY_OPERATION_WRAP), false); - } - else { - return actualWrap; - } - } - } - else if (nodeType == JavaElementType.CONDITIONAL_EXPRESSION) { - return Wrap.createWrap(getWrapType(mySettings.TERNARY_OPERATION_WRAP), false); - } - else if (nodeType == JavaElementType.ASSERT_STATEMENT) { - return Wrap.createWrap(getWrapType(mySettings.ASSERT_STATEMENT_WRAP), false); - } - else if (nodeType == JavaElementType.FOR_STATEMENT) { - return Wrap.createWrap(getWrapType(mySettings.FOR_STATEMENT_WRAP), false); - } - else if (nodeType == JavaElementType.THROWS_LIST) { - return Wrap.createWrap(getWrapType(mySettings.THROWS_LIST_WRAP), true); - } - else if (nodeType == JavaElementType.CODE_BLOCK) { - return Wrap.createWrap(Wrap.NORMAL, false); - } - else if (isAssignment()) { - return Wrap.createWrap(getWrapType(mySettings.ASSIGNMENT_WRAP), true); - } - else { - return null; - } - } - - private boolean isAssignment() { - final IElementType nodeType = myNode.getElementType(); - return nodeType == JavaElementType.ASSIGNMENT_EXPRESSION || nodeType == JavaElementType.LOCAL_VARIABLE - || nodeType == JavaElementType.FIELD; + return myWrapManager.createChildBlockWrap(this, getSettings(), this); } @Nullable @@ -375,14 +338,14 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo if (myNode.getElementType() == JavaElementType.BINARY_EXPRESSION) { final ASTNode treeParent = myNode.getTreeParent(); if (treeParent != null && treeParent.getElementType() == JavaElementType.BINARY_EXPRESSION) { - return hasTheSamePriority(treeParent); + return FormattingAstUtil.binaryExpressionHasTheSamePriority(myNode, treeParent); } } return false; } @Nullable - protected ASTNode processChild(final ArrayList result, + protected ASTNode processChild(final List result, ASTNode child, Alignment defaultAlignment, final Wrap defaultWrap, @@ -391,7 +354,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } @Nullable - protected ASTNode processChild(final ArrayList result, + protected ASTNode processChild(final List result, ASTNode child, Alignment defaultAlignment, final Wrap defaultWrap, @@ -411,7 +374,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo if (childType == JavaTokenType.LBRACE && nodeType == JavaElementType.ARRAY_INITIALIZER_EXPRESSION) { final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.ARRAY_INITIALIZER_WRAP), false); - child = processParenBlock(JavaTokenType.LBRACE, JavaTokenType.RBRACE, + child = processParenthesisBlock(JavaTokenType.LBRACE, JavaTokenType.RBRACE, result, child, WrappingStrategy.createDoNotWrapCommaStrategy(wrap), @@ -419,7 +382,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } else if (childType == JavaTokenType.LBRACE && nodeType == JavaElementType.ANNOTATION_ARRAY_INITIALIZER) { final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.ARRAY_INITIALIZER_WRAP), false); - child = processParenBlock(JavaTokenType.LBRACE, JavaTokenType.RBRACE, + child = processParenthesisBlock(JavaTokenType.LBRACE, JavaTokenType.RBRACE, result, child, WrappingStrategy.createDoNotWrapCommaStrategy(wrap), @@ -430,7 +393,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo if (mySettings.PREFER_PARAMETERS_WRAP) { wrap.ignoreParentWraps(); } - child = processParenBlock(result, + child = processParenthesisBlock(result, child, WrappingStrategy.createDoNotWrapCommaStrategy(wrap), mySettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS); @@ -438,18 +401,18 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.PARAMETER_LIST) { final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.METHOD_PARAMETERS_WRAP), false); - child = processParenBlock(result, child, + child = processParenthesisBlock(result, child, WrappingStrategy.createDoNotWrapCommaStrategy(wrap), mySettings.ALIGN_MULTILINE_PARAMETERS); } else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.ANNOTATION_PARAMETER_LIST) { final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.CALL_PARAMETERS_WRAP), false); - child = processParenBlock(result, child, + child = processParenthesisBlock(result, child, WrappingStrategy.createDoNotWrapCommaStrategy(wrap), mySettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS); } else if (childType == JavaTokenType.LPARENTH && nodeType == JavaElementType.PARENTH_EXPRESSION) { - child = processParenBlock(result, child, + child = processParenthesisBlock(result, child, WrappingStrategy.DO_NOT_WRAP, mySettings.ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION); } @@ -501,7 +464,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo return child; } - private ASTNode processField(final ArrayList result, ASTNode child, final Alignment defaultAlignment, final Wrap defaultWrap, + private ASTNode processField(final List result, ASTNode child, final Alignment defaultAlignment, final Wrap defaultWrap, final Indent childIndent) { ASTNode lastFieldInGroup = findLastFieldInGroup(child); if (lastFieldInGroup == child) { @@ -563,7 +526,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } @Nullable - private ASTNode processTernaryOperationRange(final ArrayList result, + private ASTNode processTernaryOperationRange(final List result, final ASTNode child, final Wrap defaultWrap, final Indent childIndent) { final ArrayList localResult = new ArrayList(); final Wrap wrap = arrangeChildWrap(child, defaultWrap); @@ -825,186 +788,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo myAnnotationWrap = null; } } - final ASTNode parent = child.getTreeParent(); - int role = ((CompositeElement)parent).getChildRole(child); - final IElementType nodeType = myNode.getElementType(); - if (nodeType == JavaElementType.BINARY_EXPRESSION) { - if (role == ChildRole.OPERATION_SIGN && !mySettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE) return null; - if (role == ChildRole.ROPERAND && mySettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE) return null; - return defaultWrap; - } - final IElementType childType = child.getElementType(); - if (childType == JavaElementType.EXTENDS_LIST || childType == JavaElementType.IMPLEMENTS_LIST) { - return Wrap.createWrap(getWrapType(mySettings.EXTENDS_KEYWORD_WRAP), true); - } - else if (childType == JavaElementType.THROWS_LIST) { - return Wrap.createWrap(getWrapType(mySettings.THROWS_KEYWORD_WRAP), true); - } - else if (nodeType == JavaElementType.EXTENDS_LIST || nodeType == JavaElementType.IMPLEMENTS_LIST) { - if (role == ChildRole.REFERENCE_IN_LIST) { - return defaultWrap; - } - else { - return null; - } - } - else if (nodeType == JavaElementType.THROWS_LIST) { - if (role == ChildRole.REFERENCE_IN_LIST) { - return defaultWrap; - } - else { - return null; - } - } - else if (nodeType == JavaElementType.CONDITIONAL_EXPRESSION) { - if (role == ChildRole.COLON && !mySettings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null; - if (role == ChildRole.QUEST && !mySettings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null; - if (role == ChildRole.THEN_EXPRESSION && mySettings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null; - if (role == ChildRole.ELSE_EXPRESSION && mySettings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null; - return defaultWrap; - - } - - else if (isAssignment()) { - if (role == ChildRole.INITIALIZER_EQ && mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return defaultWrap; - if (role == ChildRole.INITIALIZER_EQ && !mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null; - if (role == ChildRole.OPERATION_SIGN && mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return defaultWrap; - if (role == ChildRole.OPERATION_SIGN && !mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null; - if (role == ChildRole.INITIALIZER && !mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return defaultWrap; - if (role == ChildRole.INITIALIZER && mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null; - if (role == ChildRole.ROPERAND && !mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return defaultWrap; - if (role == ChildRole.ROPERAND && mySettings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null; - if (role == ChildRole.CLOSING_SEMICOLON) return null; - //if (role == ChildRole.TYPE) return defaultWrap; - return defaultWrap; - } - - else if (nodeType == JavaElementType.REFERENCE_EXPRESSION) { - if (role == ChildRole.DOT) { - return getReservedWrap(JavaElementType.REFERENCE_EXPRESSION); - } - else { - return defaultWrap; - } - } - else if (nodeType == JavaElementType.FOR_STATEMENT) { - if (role == ChildRole.FOR_INITIALIZATION || role == ChildRole.CONDITION || role == ChildRole.FOR_UPDATE) { - return defaultWrap; - } - if (role == ChildRole.LOOP_BODY) { - final boolean dontWrap = (childType == JavaElementType.CODE_BLOCK || childType == JavaElementType.BLOCK_STATEMENT) && - mySettings.BRACE_STYLE == CodeStyleSettings.END_OF_LINE; - return Wrap.createWrap(dontWrap ? WrapType.NONE : WrapType.NORMAL, true); - } - else { - return null; - } - - } - - else if (nodeType == JavaElementType.METHOD) { - if (role == ChildRole.THROWS_LIST) { - return defaultWrap; - } - else { - return null; - } - } - - else if (nodeType == JavaElementType.MODIFIER_LIST) { - if (childType == JavaElementType.ANNOTATION) { - return getReservedWrap(JavaElementType.MODIFIER_LIST); - } - ASTNode prevElement = getPrevElement(child); - if (prevElement != null && prevElement.getElementType() == JavaElementType.ANNOTATION) { - return getReservedWrap(JavaElementType.MODIFIER_LIST); - } - else { - return null; - } - } - else if (nodeType == JavaElementType.ASSERT_STATEMENT) { - if (role == ChildRole.CONDITION) { - return defaultWrap; - } - if (role == ChildRole.ASSERT_DESCRIPTION && !mySettings.ASSERT_STATEMENT_COLON_ON_NEXT_LINE) { - return defaultWrap; - } - if (role == ChildRole.COLON && mySettings.ASSERT_STATEMENT_COLON_ON_NEXT_LINE) { - return defaultWrap; - } - return null; - } - else if (nodeType == JavaElementType.CODE_BLOCK) { - if (role == ChildRole.STATEMENT_IN_BLOCK) { - return defaultWrap; - } - else { - return null; - } - } - - else if (nodeType == JavaElementType.IF_STATEMENT) { - if (childType == JavaElementType.IF_STATEMENT && role == ChildRole.ELSE_BRANCH && getSettings().SPECIAL_ELSE_IF_TREATMENT) { - return Wrap.createWrap(WrapType.NONE, false); - } - if (role == ChildRole.THEN_BRANCH || role == ChildRole.ELSE_BRANCH) { - if (childType == JavaElementType.BLOCK_STATEMENT) { - return null; - } - else { - return Wrap.createWrap(WrapType.NORMAL, true); - } - } - } - - else if (nodeType == JavaElementType.FOREACH_STATEMENT || nodeType == JavaElementType.WHILE_STATEMENT) { - if (role == ChildRole.LOOP_BODY) { - if (childType == JavaElementType.BLOCK_STATEMENT) { - return null; - } - else { - return Wrap.createWrap(WrapType.NORMAL, true); - } - } - } - - else if (nodeType == JavaElementType.DO_WHILE_STATEMENT) { - if (role == ChildRole.LOOP_BODY) { - return Wrap.createWrap(WrapType.NORMAL, true); - } else if (role == ChildRole.WHILE_KEYWORD) { - return Wrap.createWrap(WrapType.NORMAL, true); - } - } else if (nodeType == JavaElementType.ANNOTATION_ARRAY_INITIALIZER) { - if (role == ChildRole.ANNOTATION_VALUE) { - return Wrap.createWrap(WrapType.NORMAL, true); - } - } - - return defaultWrap; - } - - @Nullable - private static ASTNode getPrevElement(final ASTNode child) { - ASTNode result = child.getTreePrev(); - while (result != null && result.getElementType() == TokenType.WHITE_SPACE) { - result = result.getTreePrev(); - } - return result; - } - - private boolean hasTheSamePriority(final ASTNode node) { - if (node == null) return false; - if (node.getElementType() != JavaElementType.BINARY_EXPRESSION) { - return false; - } - else { - final PsiBinaryExpression expr1 = (PsiBinaryExpression)SourceTreeToPsiMap.treeElementToPsi(myNode); - final PsiBinaryExpression expr2 = (PsiBinaryExpression)SourceTreeToPsiMap.treeElementToPsi(node); - final PsiJavaToken op1 = expr1.getOperationSign(); - final PsiJavaToken op2 = expr2.getOperationSign(); - return op1.getTokenType() == op2.getTokenType(); - } + return myWrapManager.arrangeChildWrap(child, myNode, getSettings(), defaultWrap, this); } private static WrapType getWrapType(final int wrap) { @@ -1020,23 +804,19 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } } - private ASTNode processParenBlock(List result, - ASTNode child, - WrappingStrategy wrappingStrategy, - final boolean doAlign) { + private ASTNode processParenthesisBlock(List result, ASTNode child,WrappingStrategy wrappingStrategy, final boolean doAlign) { myUseChildAttributes = true; final IElementType from = JavaTokenType.LPARENTH; final IElementType to = JavaTokenType.RPARENTH; - return processParenBlock(from, to, result, child, wrappingStrategy, doAlign); - + return processParenthesisBlock(from, to, result, child, wrappingStrategy, doAlign); } - private ASTNode processParenBlock(final IElementType from, + private ASTNode processParenthesisBlock(final IElementType from, final IElementType to, final List result, ASTNode child, final WrappingStrategy wrappingStrategy, final boolean doAlign ) { @@ -1049,7 +829,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo boolean isAfterIncomplete = false; ASTNode prev = child; - int startOffset = child.getTextRange().getStartOffset(); while (child != null) { isAfterIncomplete = isAfterIncomplete || child.getElementType() == TokenType.ERROR_ELEMENT || child.getElementType() == JavaElementType.EMPTY_EXPRESSION; @@ -1066,10 +845,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } else { final IElementType elementType = child.getElementType(); - result.add(createJavaBlock(child, mySettings, internalIndent, - wrappingStrategy.getWrap(elementType), - alignmentStrategy.getAlignment(elementType), - startOffset)); + processChild(result, child, alignmentStrategy.getAlignment(elementType), wrappingStrategy.getWrap(elementType), internalIndent); if (to == null) {//process only one statement return child; } @@ -1077,7 +853,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo isAfterIncomplete = false; } prev = child; - startOffset += child.getTextLength(); child = child.getTreeNext(); } @@ -1202,9 +977,31 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo return false; } - protected abstract Wrap getReservedWrap(final IElementType elementType); + /** + * Note: this method is considered to be a legacy heritage and is assumed to be removed as soon as formatting processing + * is refactored + * + * @param elementType target element type + * @return null all the time + */ + public Wrap getReservedWrap(IElementType elementType) { + return null; + } - protected abstract void setReservedWrap(final Wrap reservedWrap, final IElementType operationType); + /** + * Defines contract for associating operation type and particular wrap instance. I.e. given wrap object may be returned + * from subsequent {@link #getReservedWrap(IElementType)} call if given operation type is used as an argument there. + *

+ * Default implementation ({@link AbstractJavaBlock#setReservedWrap(Wrap, IElementType)}) does nothing. + *

+ * Note: this method is considered to be a legacy heritage and is assumed to be removed as soon as formatting processing + * is refactored + * + * @param reservedWrap reserved wrap instance + * @param operationType target operation type to associate with the given wrap instance + */ + protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) { + } @Nullable protected static ASTNode getTreeNode(final Block child2) { From 2cd59d710d88695c686f4603987256868211a253 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:20:58 +0400 Subject: [PATCH 13/45] IDEA-43962 Indentation error on deep nesting levels 1. Dummy methods are moved to the super class; 2. Green code policy is applied; --- .../psi/formatter/java/BlockContainingJavaBlock.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java index 7bae1e7e45a9..6baba318732e 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java @@ -71,7 +71,7 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{ } } - private int calcNewState(final ASTNode child, final int state) { + private static int calcNewState(final ASTNode child, final int state) { if (state == BEFORE_FIRST) { if (child.getElementType() == ElementType.ELSE_KEYWORD) { return AFTER_ELSE; @@ -152,13 +152,13 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{ return Indent.getContinuationIndent(); } - private boolean isSimpleStatement(final ASTNode child) { + private static boolean isSimpleStatement(final ASTNode child) { if (child.getElementType() == ElementType.BLOCK_STATEMENT) return false; if (!ElementType.STATEMENT_BIT_SET.contains(child.getElementType())) return false; return isStatement(child, child.getTreeParent()); } - private boolean isPartOfCodeBlock(final ASTNode child) { + private static boolean isPartOfCodeBlock(final ASTNode child) { if (child == null) return false; if (child.getElementType() == ElementType.BLOCK_STATEMENT) return true; if (child.getElementType() == ElementType.CODE_BLOCK) return true; @@ -168,12 +168,7 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{ return child.getElementType() == JavaDocElementType.DOC_COMMENT; } - protected Wrap getReservedWrap(final IElementType elementType) { - return null; - } - protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) { - } @NotNull public ChildAttributes getChildAttributes(final int newChildIndex) { From 3d68e93737fc97154b6ce7a8f06887d9437c2763 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:22:03 +0400 Subject: [PATCH 14/45] IDEA-43962 Indentation error on deep nesting levels 1. Dummy methods are moved to the super class; 2. Green code policy is applied; --- .../psi/formatter/java/CodeBlockBlock.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java index 53a707bfd96a..f93962a6b00c 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java @@ -27,6 +27,7 @@ import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.StdTokenSets; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -97,6 +98,7 @@ public class CodeBlockBlock extends AbstractJavaBlock { } } + @Nullable private ASTNode composeCodeBlock(final ArrayList result, ASTNode child, final Indent indent) { final ArrayList localResult = new ArrayList(); processChild(localResult, child, null, null, Indent.getNoneIndent()); @@ -125,6 +127,7 @@ public class CodeBlockBlock extends AbstractJavaBlock { return result; } + @Nullable private ASTNode processCaseAndStatementAfter(final ArrayList result, ASTNode child, final Alignment childAlignment, @@ -159,7 +162,7 @@ public class CodeBlockBlock extends AbstractJavaBlock { return null; } - private boolean isBreakOrReturn(final ASTNode child) { + private static boolean isBreakOrReturn(final ASTNode child) { IElementType elementType = child.getElementType(); return JavaElementType.BREAK_STATEMENT == elementType || JavaElementType.RETURN_STATEMENT == elementType; } @@ -193,7 +196,7 @@ public class CodeBlockBlock extends AbstractJavaBlock { return result; } - private int calcNewState(final ASTNode child, int state) { + private static int calcNewState(final ASTNode child, int state) { switch (state) { case BEFORE_FIRST: { if (StdTokenSets.COMMENT_BIT_SET.contains(child.getElementType())) { @@ -218,7 +221,7 @@ public class CodeBlockBlock extends AbstractJavaBlock { return INSIDE_BODY; } - private boolean isLBrace(final ASTNode child) { + private static boolean isLBrace(final ASTNode child) { return child.getElementType() == ElementType.LBRACE; } @@ -250,7 +253,7 @@ public class CodeBlockBlock extends AbstractJavaBlock { } } - private boolean isRBrace(final ASTNode child) { + private static boolean isRBrace(final ASTNode child) { return child.getElementType() == ElementType.RBRACE; } @@ -269,11 +272,4 @@ public class CodeBlockBlock extends AbstractJavaBlock { } } } - - protected Wrap getReservedWrap(final IElementType elementType) { - return null; - } - - protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) { - } } From 77e2696239326ae149c5ce89ef73d2f96b5558e6 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:22:21 +0400 Subject: [PATCH 15/45] IDEA-43962 Indentation error on deep nesting levels 1. Dummy methods are moved to the super class; 2. Green code policy is applied; --- .../com/intellij/psi/formatter/java/DocCommentBlock.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java index 9dc2195cf85f..50a8db964e9f 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java @@ -20,7 +20,6 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.impl.source.tree.ElementType; -import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -48,13 +47,6 @@ public class DocCommentBlock extends AbstractJavaBlock{ } - protected Wrap getReservedWrap(final IElementType elementType) { - return null; - } - - protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) { - } - @NotNull public ChildAttributes getChildAttributes(final int newChildIndex) { return new ChildAttributes(Indent.getSpaceIndent(1), null); From 83a8efa4391e54c96d44b3f2b492d7c7d246fb2f Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:22:41 +0400 Subject: [PATCH 16/45] IDEA-43962 Indentation error on deep nesting levels 1. Dummy methods are moved to the super class; 2. Green code policy is applied; --- .../com/intellij/psi/formatter/java/ExtendsListBlock.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/ExtendsListBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/ExtendsListBlock.java index a259737e575c..6208374f225d 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/ExtendsListBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/ExtendsListBlock.java @@ -23,7 +23,6 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.impl.source.tree.ElementType; -import com.intellij.psi.tree.IElementType; import java.util.ArrayList; import java.util.List; @@ -77,11 +76,4 @@ public class ExtendsListBlock extends AbstractJavaBlock{ } return false; } - - protected Wrap getReservedWrap(final IElementType elementType) { - return null; - } - - protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) { - } } From 02421d016ad413b4a04826ba525f1f1acf3be97b Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:23:18 +0400 Subject: [PATCH 17/45] IDEA-43962 Indentation error on deep nesting levels 1. Dummy methods are moved to the super class; 2. Green code policy is applied; --- .../intellij/psi/formatter/java/LabeledJavaBlock.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/LabeledJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/LabeledJavaBlock.java index 23cfa78a18fa..926ad80db2e3 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/LabeledJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/LabeledJavaBlock.java @@ -21,7 +21,6 @@ import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.impl.source.tree.ElementType; -import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -46,7 +45,7 @@ public class LabeledJavaBlock extends AbstractJavaBlock{ result.add(createJavaBlock(child, mySettings, currentIndent, currentWrap, null)); if (child.getElementType() == ElementType.COLON) { currentIndent = Indent.getNoneIndent(); - currentWrap =Wrap.createWrap(Wrap.ALWAYS, true); + currentWrap =Wrap.createWrap(WrapType.ALWAYS, true); } } child = child.getTreeNext(); @@ -62,13 +61,6 @@ public class LabeledJavaBlock extends AbstractJavaBlock{ } } - protected Wrap getReservedWrap(final IElementType elementType) { - return null; - } - - protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) { - } - @Override @NotNull public ChildAttributes getChildAttributes(final int newChildIndex) { From 9c512f3209ca43a32345970563d2b0a28aa782ed Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:23:52 +0400 Subject: [PATCH 18/45] IDEA-43962 Indentation error on deep nesting levels Dummy methods are moved to the super class --- .../psi/formatter/java/MethodCallExpressionBlock.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/MethodCallExpressionBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/MethodCallExpressionBlock.java index 46fa09436c79..78bfa914d523 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/MethodCallExpressionBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/MethodCallExpressionBlock.java @@ -21,7 +21,6 @@ import com.intellij.formatting.Alignment; import com.intellij.formatting.Indent; import com.intellij.formatting.Block; import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.tree.IElementType; import java.util.List; @@ -33,11 +32,4 @@ public class MethodCallExpressionBlock extends AbstractJavaBlock{ protected List buildChildren() { return null; } - - protected Wrap getReservedWrap(final IElementType elementType) { - return null; - } - - protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) { - } } From 7baad4cfb383550a2e7b2bc2899b325bcdfadd07 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:25:01 +0400 Subject: [PATCH 19/45] IDEA-43962 Indentation error on deep nesting levels 1. Dummy methods are moved to the super class; 2. Green code policy is applied; --- .../com/intellij/psi/formatter/java/SimpleJavaBlock.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java index d3fab07cf9c8..354bdf1351da 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java @@ -70,7 +70,7 @@ public class SimpleJavaBlock extends AbstractJavaBlock { if (astNode != child && child != null) { offset = child.getTextRange().getStartOffset(); } - if (indent != null && !(myNode.getPsi() instanceof PsiFile) && child.getElementType() != ElementType.MODIFIER_LIST) { + if (indent != null && !(myNode.getPsi() instanceof PsiFile) && child != null && child.getElementType() != ElementType.MODIFIER_LIST) { indent = Indent.getContinuationIndent(); } //indent = FormatterEx.getInstance().getContinuationIndent(); @@ -107,10 +107,12 @@ public class SimpleJavaBlock extends AbstractJavaBlock { } } - protected Wrap getReservedWrap(final IElementType elementType) { + @Override + public Wrap getReservedWrap(final IElementType elementType) { return myReservedWrap.get(elementType); } + @Override protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) { myReservedWrap.put(operationType, reservedWrap); } From 7c3e5247643de01777ea35b3b14faee66366bcb1 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:25:53 +0400 Subject: [PATCH 20/45] IDEA-43962 Indentation error on deep nesting levels 1. Convenient factory method is introduced; 2. Legacy constants are marked as deprecated; --- .../src/com/intellij/formatting/Wrap.java | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/platform/lang-api/src/com/intellij/formatting/Wrap.java b/platform/lang-api/src/com/intellij/formatting/Wrap.java index 54a311f4f76b..cbc633ce12c8 100644 --- a/platform/lang-api/src/com/intellij/formatting/Wrap.java +++ b/platform/lang-api/src/com/intellij/formatting/Wrap.java @@ -15,8 +15,6 @@ */ package com.intellij.formatting; -import com.intellij.openapi.diagnostic.Logger; - /** * The wrap setting for a formatting model block. Indicates the conditions under which a line break * is inserted before the block when formatting, if the block extends beyond the @@ -34,15 +32,46 @@ public abstract class Wrap { private static WrapFactory myFactory; + /** + * @deprecated use {@link WrapType#ALWAYS} instead + */ + @Deprecated public static WrapType ALWAYS = WrapType.ALWAYS; + + /** + * @deprecated use {@link WrapType#NORMAL} instead + */ + @Deprecated public static WrapType NORMAL = WrapType.NORMAL; + + /** + * @deprecated use {@link WrapType#NONE} instead + */ + @Deprecated public static WrapType NONE = WrapType.NONE; + + /** + * @deprecated use {@link WrapType#CHOP_DOWN_IF_LONG} instead + */ + @SuppressWarnings({"UnusedDeclaration"}) + @Deprecated public static WrapType CHOP_DOWN_IF_LONG = WrapType.CHOP_DOWN_IF_LONG; static void setFactory(WrapFactory factory) { myFactory = factory; } + /** + * Creates a block wrap setting of the legacy representation of specified wrap type (see {@link WrapType#getLegacyRepresentation()}). + * + * @param type the type of the wrap setting. + * @param wrapFirstElement if true, the first element in a sequence of elements of the same type is also wrapped. + * @return the wrap setting instance. + */ + public static Wrap createWrap(final int type, final boolean wrapFirstElement) { + return myFactory.createWrap(WrapType.byLegacyRepresentation(type), wrapFirstElement); + } + /** * Creates a block wrap setting of the specified type. * From 76e3db2fa9f49c5c473b08c16ba1ba972d2d2bda Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:26:34 +0400 Subject: [PATCH 21/45] IDEA-43962 Indentation error on deep nesting levels Provided bridging facilities between new and old wrap types api --- .../src/com/intellij/formatting/WrapType.java | 53 +++++++++++++++++-- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/platform/lang-api/src/com/intellij/formatting/WrapType.java b/platform/lang-api/src/com/intellij/formatting/WrapType.java index 02579d89718a..15577183877a 100644 --- a/platform/lang-api/src/com/intellij/formatting/WrapType.java +++ b/platform/lang-api/src/com/intellij/formatting/WrapType.java @@ -15,6 +15,11 @@ */ package com.intellij.formatting; +import com.intellij.psi.codeStyle.CodeStyleSettings; + +import java.util.HashMap; +import java.util.Map; + /** * Defines possible types of a wrap. * @@ -23,29 +28,69 @@ package com.intellij.formatting; */ public enum WrapType { + /** * A line break is always inserted before the start of the element. * This corresponds to the "Wrap always" setting in Global Code Style | Wrapping. */ - ALWAYS, + ALWAYS(CodeStyleSettings.WRAP_ALWAYS), /** * A line break is inserted before the start of the element if the right edge * of the element goes beyond the specified wrap margin. * This corresponds to the "Wrap if long" setting in Global Code Style | Wrapping. */ - NORMAL, + NORMAL(CodeStyleSettings.WRAP_AS_NEEDED), /** * A line break is never inserted before the start of the element. * This corresponds to the "Do not wrap" setting in Global Code Style | Wrapping. */ - NONE, + NONE(CodeStyleSettings.DO_NOT_WRAP), /** * A line break is inserted before the start of the element if it is a part * of list of elements of the same type and at least one of the elements was wrapped. * This corresponds to the "Chop down if long" setting in Global Code Style | Wrapping. */ - CHOP_DOWN_IF_LONG + CHOP_DOWN_IF_LONG(CodeStyleSettings.WRAP_ON_EVERY_ITEM); + + private static final Map LEGACY_MAPPINGS = new HashMap(); + + static { + for (WrapType wrapType : values()) { + LEGACY_MAPPINGS.put(wrapType.getLegacyRepresentation(), wrapType); + } + } + + private final int myLegacyRepresentation; + + WrapType(int legacyRepresentation) { + myLegacyRepresentation = legacyRepresentation; + } + + /** + * Allows to retrieve wrap type by it's legacy non-type-safe representation (see {@link #getLegacyRepresentation()}). + * + * @param value legacy representation of the target wrap type + * @return wrap type which {@link #getLegacyRepresentation() legacyRepresentation} is equal to the given value if any; + * {@link #CHOP_DOWN_IF_LONG} otherwise + */ + public static WrapType byLegacyRepresentation(int value) { + WrapType result = LEGACY_MAPPINGS.get(value); + return result == null ? CHOP_DOWN_IF_LONG : result; + } + + /** + * Wrapping types were used as a primitive constants during this enum introduction (e.g. {@link CodeStyleSettings#DO_NOT_WRAP} etc). + *

+ * It's possible to map that legacy representation to the object-level enum member via {@link #byLegacyRepresentation(int)}. + *

+ * Current getter exposes legacy value associated with the current object-level wrap type representation. + * + * @return legacy representation of the current wrap type + */ + public int getLegacyRepresentation() { + return myLegacyRepresentation; + } } From 3754c7245944519dcd67e03552710f797be31850 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:28:41 +0400 Subject: [PATCH 22/45] IDEA-43962 Indentation error on deep nesting levels Green code policy is applied --- .../src/com/intellij/formatting/FormatterImpl.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java index aae99190c915..da607feaca2e 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java @@ -279,8 +279,7 @@ public class FormatterImpl extends FormatterEx { boolean wsContainsCaret = whiteSpace.getStartOffset() <= offset && offset < whiteSpace.getEndOffset(); - final CharSequence text = getCharSequence(documentModel); - int lineStartOffset = getLineStartOffset(offset, whiteSpace, text, documentModel); + int lineStartOffset = getLineStartOffset(offset, whiteSpace, documentModel); final IndentInfo indent = calcIndent(offset, documentModel, processor, whiteSpace); @@ -325,7 +324,7 @@ public class FormatterImpl extends FormatterEx final WhiteSpace whiteSpace = blockAfterOffset.getWhiteSpace(); final IndentInfo indent = calcIndent(offset, documentModel, processor, whiteSpace); - return indent.generateNewWhiteSpace(indentOptions).toString(); + return indent.generateNewWhiteSpace(indentOptions); } return null; } @@ -355,10 +354,10 @@ public class FormatterImpl extends FormatterEx private static int getLineStartOffset(final int offset, final WhiteSpace whiteSpace, - final CharSequence text, final FormattingDocumentModel documentModel) { int lineStartOffset = offset; + CharSequence text = getCharSequence(documentModel); lineStartOffset = CharArrayUtil.shiftBackwardUntil(text, lineStartOffset, " \t\n"); if (lineStartOffset > whiteSpace.getStartOffset()) { if (lineStartOffset >= text.length()) lineStartOffset = text.length() - 1; @@ -572,10 +571,6 @@ public class FormatterImpl extends FormatterEx return myContinutationWithoutFirstIndent; } - public static int getLineFeedsToModified(final FormattingDocumentModel model, final int offset, final int startOffset) { - return model.getLineNumber(offset) - model.getLineNumber(startOffset); - } - private final Object DISABLING_LOCK = new Object(); public boolean isDisabled() { From 06f8583069a6505f23ae2d0c972fab8b42ecd22b Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 21 Apr 2010 17:12:08 +0400 Subject: [PATCH 23/45] added before event firing --- .../src/com/intellij/util/FileContentUtil.java | 13 +++++++------ .../src/com/intellij/openapi/vfs/VirtualFile.java | 7 ++++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/platform/lang-api/src/com/intellij/util/FileContentUtil.java b/platform/lang-api/src/com/intellij/util/FileContentUtil.java index 5cf631476812..d627f9c15300 100644 --- a/platform/lang-api/src/com/intellij/util/FileContentUtil.java +++ b/platform/lang-api/src/com/intellij/util/FileContentUtil.java @@ -30,6 +30,7 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import gnu.trove.THashSet; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -42,7 +43,7 @@ import java.util.Set; * @author peter */ public class FileContentUtil { - public static final String FORCE_RELOAD_REQUESTOR = "FileContentUtil.saveOrReload"; + @NonNls public static final String FORCE_RELOAD_REQUESTOR = "FileContentUtil.saveOrReload"; private FileContentUtil() { } @@ -67,23 +68,23 @@ public class FileContentUtil { } public static void reparseFiles(@NotNull final Project project, @NotNull final Collection files, boolean includeOpenFiles) { - final Set list = new THashSet(); + final Set events = new THashSet(); for (VirtualFile file : files) { - saveOrReload(file, list); + saveOrReload(file, events); } if (includeOpenFiles) { for (VirtualFile open : FileEditorManager.getInstance(project).getOpenFiles()) { if (!files.contains(open)) { - saveOrReload(open, list); + saveOrReload(open, events); } } } ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { ApplicationManager.getApplication().getMessageBus().syncPublisher(VirtualFileManager.VFS_CHANGES) - .before(new ArrayList(list)); + .before(new ArrayList(events)); ApplicationManager.getApplication().getMessageBus().syncPublisher(VirtualFileManager.VFS_CHANGES) - .after(new ArrayList(list)); + .after(new ArrayList(events)); } }); } diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/VirtualFile.java b/platform/platform-api/src/com/intellij/openapi/vfs/VirtualFile.java index f60217bfd97a..5f4c0337dda3 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/VirtualFile.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/VirtualFile.java @@ -24,6 +24,7 @@ import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.encoding.EncodingManager; +import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent; import com.intellij.util.Icons; import org.jetbrains.annotations.NonNls; @@ -36,6 +37,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; import java.util.Collections; +import java.util.List; /** * Represents a file in {@link VirtualFileSystem}. A particular file is represented by the same @@ -451,7 +453,10 @@ public abstract class VirtualFile extends UserDataHolderBase implements Modifica if (isValid() && !application.isDisposed()) { application.runWriteAction(new Runnable(){ public void run() { - application.getMessageBus().syncPublisher(VirtualFileManager.VFS_CHANGES).after(Collections.singletonList(new VFilePropertyChangeEvent(this, VirtualFile.this, PROP_ENCODING, old, charset, false))); + List events = Collections.singletonList(new VFilePropertyChangeEvent(this, VirtualFile.this, PROP_ENCODING, old, charset, false)); + BulkFileListener listener = application.getMessageBus().syncPublisher(VirtualFileManager.VFS_CHANGES); + listener.before(events); + listener.after(events); } }); } From 2e8ee403314f8b66b7b89b06c20d82fc239c769c Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:29:39 +0400 Subject: [PATCH 24/45] IDEA-43962 Indentation error on deep nesting levels Initial version. Consists of code moved from AbstractJavaBlock class. --- .../psi/formatter/java/FormattingAstUtil.java | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 java/java-impl/src/com/intellij/psi/formatter/java/FormattingAstUtil.java diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/FormattingAstUtil.java b/java/java-impl/src/com/intellij/psi/formatter/java/FormattingAstUtil.java new file mode 100644 index 000000000000..f23eb0f72a60 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/formatter/java/FormattingAstUtil.java @@ -0,0 +1,92 @@ +/* + * Copyright 2000-2010 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.formatter.java; + +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiBinaryExpression; +import com.intellij.psi.TokenType; +import com.intellij.psi.impl.source.SourceTreeToPsiMap; +import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.Nullable; + +import java.util.HashSet; +import java.util.Set; + +import static java.util.Arrays.asList; + +/** + * Contains various utility methods for AST processing during code formatting. + * + * @author Denis Zhdanov + * @since Apr 21, 2010 4:02:17 PM + */ +public class FormattingAstUtil { + + /** Holds type of AST elements that are considered to be assignments. */ + private static final Set ASSIGNMENT_ELEMENT_TYPES = new HashSet(asList( + JavaElementType.ASSIGNMENT_EXPRESSION, JavaElementType.LOCAL_VARIABLE, JavaElementType.FIELD + )); + + private FormattingAstUtil() { + } + + /** + * Tries to get previous non-white space AST node for the given one. + * + * @param node base node which left non-white space sibling is to be found + * @return left non-white space sibling of the given node if any; null otherwise + */ + @Nullable + public static ASTNode getPrevElement(final ASTNode node) { + ASTNode result = node.getTreePrev(); + while (result != null && result.getElementType() == TokenType.WHITE_SPACE) { + result = result.getTreePrev(); + } + return result; + } + + /** + * Allows to answer if given node wraps assignement operation. + * + * @param node node to check + * @return true if given node wraps assignement operation; false otherwise + */ + public static boolean isAssignment(ASTNode node) { + return ASSIGNMENT_ELEMENT_TYPES.contains(node.getElementType()); + } + + /** + * Allows to check if given AST nodes refer to binary expressions and have the same priority. + * + * @param node1 node to check + * @param node2 node to check + * @return true if given nodes are binary expressions and have the same priority; + * false otherwise + */ + public static boolean binaryExpressionHasTheSamePriority(ASTNode node1, ASTNode node2) { + if (node1 == null || node2 == null) { + return false; + } + + if (node1.getElementType() != JavaElementType.BINARY_EXPRESSION || node2.getElementType() != JavaElementType.BINARY_EXPRESSION) { + return false; + } + PsiBinaryExpression expression1 = (PsiBinaryExpression)SourceTreeToPsiMap.treeElementToPsi(node1); + PsiBinaryExpression expression2 = (PsiBinaryExpression)SourceTreeToPsiMap.treeElementToPsi(node2); + return expression1.getOperationSign().getTokenType() == expression2.getOperationSign().getTokenType(); + } +} From f2ec038199ee31f2038228b6112ee2cd6dcea815 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:31:14 +0400 Subject: [PATCH 25/45] IDEA-43962 Indentation error on deep nesting levels Initial version. Consists of code moved from AbstractJavaBlock.createChildWrap() method. --- .../wrap/impl/JavaChildBlockWrapFactory.java | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildBlockWrapFactory.java diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildBlockWrapFactory.java b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildBlockWrapFactory.java new file mode 100644 index 000000000000..8bcf0e7d4dfa --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildBlockWrapFactory.java @@ -0,0 +1,94 @@ +/* + * Copyright 2000-2010 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.formatter.java.wrap.impl; + +import com.intellij.formatting.ASTBlock; +import com.intellij.formatting.Wrap; +import com.intellij.formatting.WrapType; +import com.intellij.lang.ASTNode; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.formatter.java.FormattingAstUtil; +import com.intellij.psi.formatter.java.wrap.ReservedWrapsProvider; +import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.Nullable; + +/** + * Encapsulates algorithm of construction {@link Wrap wraps} for sub-blocks of particular {@link ASTBlock block} taking into + * consideration current formatting settings. + *

+ * Thread-safe. + * + * @author Denis Zhdanov + * @since Apr 21, 2010 4:49:49 PM + */ +public class JavaChildBlockWrapFactory { + + /** + * Creates {@link Wrap wrap} to be used with the children blocks of the the given block. + * + * @param block target block which sub-blocks should use wrap created by the current method + * @param settings code formatting settings to consider during wrap construction + * @param reservedWrapsProvider reserved {@code 'element type -> wrap instance'} mappings provider. Note: this + * argument is considered to be a part of legacy heritage and is intended to be removed as + * soon as formatting code refactoring is done + * @return wrap to use for the sub-blocks of the given block + */ + @Nullable + public Wrap create(ASTBlock block, CodeStyleSettings settings, ReservedWrapsProvider reservedWrapsProvider) { + ASTNode node = block.getNode(); + Wrap wrap = block.getWrap(); + final IElementType nodeType = node.getElementType(); + if (nodeType == JavaElementType.EXTENDS_LIST || nodeType == JavaElementType.IMPLEMENTS_LIST) { + return Wrap.createWrap(settings.EXTENDS_LIST_WRAP, false); + } + else if (nodeType == JavaElementType.BINARY_EXPRESSION) { + Wrap actualWrap = wrap != null ? wrap : reservedWrapsProvider.getReservedWrap(JavaElementType.BINARY_EXPRESSION); + if (actualWrap == null) { + return Wrap.createWrap(settings.BINARY_OPERATION_WRAP, false); + } + else { + if (!FormattingAstUtil.binaryExpressionHasTheSamePriority(node, node.getTreeParent())) { + return Wrap.createChildWrap(actualWrap, WrapType.byLegacyRepresentation(settings.BINARY_OPERATION_WRAP), false); + } + else { + return actualWrap; + } + } + } + else if (nodeType == JavaElementType.CONDITIONAL_EXPRESSION) { + return Wrap.createWrap(settings.TERNARY_OPERATION_WRAP, false); + } + else if (nodeType == JavaElementType.ASSERT_STATEMENT) { + return Wrap.createWrap(settings.ASSERT_STATEMENT_WRAP, false); + } + else if (nodeType == JavaElementType.FOR_STATEMENT) { + return Wrap.createWrap(settings.FOR_STATEMENT_WRAP, false); + } + else if (nodeType == JavaElementType.THROWS_LIST) { + return Wrap.createWrap(settings.THROWS_LIST_WRAP, true); + } + else if (nodeType == JavaElementType.CODE_BLOCK) { + return Wrap.createWrap(Wrap.NORMAL, false); + } + else if (FormattingAstUtil.isAssignment(node)) { + return Wrap.createWrap(settings.ASSIGNMENT_WRAP, true); + } + else { + return null; + } + } +} From 5e3c6fa50ad28911d369da2048c461746251b133 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:46:56 +0400 Subject: [PATCH 26/45] IDEA-43962 Indentation error on deep nesting levels Initial version. Encapsulates AbstractJavaBlock.getReservedWrap(). --- .../java/wrap/ReservedWrapsProvider.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 java/java-impl/src/com/intellij/psi/formatter/java/wrap/ReservedWrapsProvider.java diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/ReservedWrapsProvider.java b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/ReservedWrapsProvider.java new file mode 100644 index 000000000000..d166d858b531 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/ReservedWrapsProvider.java @@ -0,0 +1,42 @@ +/* + * Copyright 2000-2010 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.formatter.java.wrap; + +import com.intellij.formatting.Wrap; +import com.intellij.psi.formatter.java.AbstractJavaBlock; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.Nullable; + +/** + * Defines contract for using predefined reserved wraps. + *

+ * Note: this interface is introduced for encapsulating legacy {@link AbstractJavaBlock#getReservedWrap(IElementType)} + * method and most probably will be removed as soon as formatting stuff is refactored. + * + * @author Denis Zhdanov + * @since Apr 21, 2010 3:43:17 PM + */ +public interface ReservedWrapsProvider { + + /** + * Allows to retrieve predefined {@link Wrap} object for the given element type if any. + * + * @param elementType target element type + * @return predefined wrap for the given element type if any; null otherwise + */ + @Nullable + Wrap getReservedWrap(IElementType elementType); +} From 3a9a4f3b782e265f37cd3b4a2e772cad6d0230dc Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:49:15 +0400 Subject: [PATCH 27/45] IDEA-43962 Indentation error on deep nesting levels 1. Meaningfull toString() is move to the super class; 2. Green code policy is applied; --- .../com/intellij/formatting/LeafBlockWrapper.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/LeafBlockWrapper.java b/platform/lang-impl/src/com/intellij/formatting/LeafBlockWrapper.java index 12328f11956e..171ac65b1357 100644 --- a/platform/lang-impl/src/com/intellij/formatting/LeafBlockWrapper.java +++ b/platform/lang-impl/src/com/intellij/formatting/LeafBlockWrapper.java @@ -20,8 +20,6 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.codeStyle.CodeStyleSettings; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; - class LeafBlockWrapper extends AbstractBlockWrapper { private static final int CONTAIN_LINE_FEEDS = 4; private static final int READ_ONLY = 8; @@ -149,12 +147,7 @@ class LeafBlockWrapper extends AbstractBlockWrapper { } } - ArrayList ignored = new ArrayList(); - IndentData result = myParent.getChildOffset(this, options, this.getStartOffset()); - if (!ignored.isEmpty()) { - result = result.add(ignored.get(ignored.size() - 1)); - } - return result; + return myParent.getChildOffset(this, options, this.getStartOffset()); } public void setSpaceProperty(final SpacingImpl currentSpaceProperty) { @@ -191,8 +184,4 @@ class LeafBlockWrapper extends AbstractBlockWrapper { return new TextRange(myStart, myEnd); } - @Override - public String toString() { - return "LeafBlockWrapper(" + myStart + "-" + myEnd + ")"; - } } From a03d4ce9e8903e1cea9cf040d71c46d0d3a2c7fd Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:50:33 +0400 Subject: [PATCH 28/45] IDEA-43962 Indentation error on deep nesting levels Initial version --- .../formatter/java/wrap/JavaWrapManager.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 java/java-impl/src/com/intellij/psi/formatter/java/wrap/JavaWrapManager.java diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/JavaWrapManager.java b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/JavaWrapManager.java new file mode 100644 index 000000000000..058ebabf1133 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/JavaWrapManager.java @@ -0,0 +1,100 @@ +/* + * Copyright 2000-2010 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.formatter.java.wrap; + +import com.intellij.formatting.ASTBlock; +import com.intellij.formatting.Block; +import com.intellij.formatting.Wrap; +import com.intellij.lang.ASTNode; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.formatter.java.wrap.impl.JavaChildBlockWrapFactory; +import com.intellij.psi.formatter.java.wrap.impl.JavaChildWrapArranger; +import org.jetbrains.annotations.Nullable; + +/** + * Defines common contract for {@link Wrap wraps} manipulation during java {@link Block blockes} processing + *

+ * This class is intended to serve as a facade for various fine-grained wrap processing classes. + *

+ * This class is not singleton but it's thread-safe and provides single-point-of-usage field {@link #INSTANCE}. + *

+ * Thread-safe. + * + * @author Denis Zhdanov + * @since Apr 21, 2010 2:19:17 PM + */ +public class JavaWrapManager { + + /** Single-point-of-usage field. */ + public static final JavaWrapManager INSTANCE = new JavaWrapManager(); + + private final JavaChildWrapArranger myChildArranger; + private final JavaChildBlockWrapFactory myChildBlockFactory; + + /** + * Creates new JavaWrapManager object with default wrapping services. + */ + public JavaWrapManager() { + this(new JavaChildWrapArranger(), new JavaChildBlockWrapFactory()); + } + + public JavaWrapManager(JavaChildWrapArranger childWrapArranger, JavaChildBlockWrapFactory childBlockWrapFactory) { + myChildArranger = childWrapArranger; + myChildBlockFactory = childBlockWrapFactory; + } + + /** + * Tries to define the wrap to use for the {@link Block block} for the given 'child' node. It's assumed that + * given 'child' node is descendant (direct or indirect) of the given 'parent' node. + * I.e. 'parent' node defines usage context for the 'child' node. + * + * @param child child node which {@link Wrap wrap} is to be defined + * @param parent direct or indirect parent of the given 'child' node. Defines usage context + * of 'child' node processing + * @param settings code style settings to use during wrap definition + * @param suggestedWrap wrap suggested to use by clients of current class. I.e. those clients offer wrap to + * use based on their information about current processing state. However, it's possible + * that they don't know details of fine-grained wrap definition algorithm encapsulated + * at the current class. Hence, this method takes suggested wrap into consideration but + * is not required to use it all the time node based on the given parameters + * @param reservedWrapsProvider reserved {@code 'element type -> wrap instance'} mappings provider. Note: this + * argument is considered to be a part of legacy heritage and is intended to be removed as + * soon as formatting code refactoring is done + * @return wrap to use for the given 'child' node if it's possible to define the one; + * null otherwise + */ + @Nullable + public Wrap arrangeChildWrap(ASTNode child, ASTNode parent, CodeStyleSettings settings, Wrap suggestedWrap, + ReservedWrapsProvider reservedWrapsProvider) + { + return myChildArranger.arrange(child, parent, settings, suggestedWrap, reservedWrapsProvider); + } + + /** + * Creates {@link Wrap wrap} to be used with the children blocks of the the given block. + * + * @param block target block which sub-blocks should use wrap created by the current method + * @param settings code formatting settings to consider during wrap construction + * @param reservedWrapsProvider reserved {@code 'element type -> wrap instance'} mappings provider. Note: this + * argument is considered to be a part of legacy heritage and is intended to be removed as + * soon as formatting code refactoring is done + * @return wrap to use for the sub-blocks of the given block + */ + @Nullable + public Wrap createChildBlockWrap(ASTBlock block, CodeStyleSettings settings, ReservedWrapsProvider reservedWrapsProvider) { + return myChildBlockFactory.create(block, settings, reservedWrapsProvider); + } +} From 73802b14bbc169a1f5c5fa736f455c020588f56d Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:50:53 +0400 Subject: [PATCH 29/45] IDEA-43962 Indentation error on deep nesting levels Javadoc is corrected --- .../src/com/intellij/formatting/FormatProcessor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java index 80d6a104d2ca..7a97a87becde 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java @@ -629,9 +629,9 @@ class FormatProcessor { } /** - * Tries to get align-implied indent of the line that contains current block. + * Tries to get align-implied indent of the current block. * - * @return indent of the line that contains current block if any; null otherwise + * @return indent of the current block if any; null otherwise */ @Nullable private IndentData getAlignOffset() { From 5c5ce1f22019ac267917dd606bf413ed4f500f27 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 16:51:57 +0400 Subject: [PATCH 30/45] IDEA-43962 Indentation error on deep nesting levels Initial version. Encapsulates functionality that remained at AbstractJavaBlock.arrangeChildWrap(). --- .../java/wrap/impl/JavaChildWrapArranger.java | 227 ++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java new file mode 100644 index 000000000000..e4f1c2fb53cf --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/formatter/java/wrap/impl/JavaChildWrapArranger.java @@ -0,0 +1,227 @@ +/* + * Copyright 2000-2010 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.formatter.java.wrap.impl; + +import com.intellij.formatting.Wrap; +import com.intellij.formatting.WrapType; +import com.intellij.lang.ASTNode; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.formatter.java.FormattingAstUtil; +import com.intellij.psi.formatter.java.wrap.JavaWrapManager; +import com.intellij.psi.formatter.java.wrap.ReservedWrapsProvider; +import com.intellij.psi.impl.source.tree.ChildRole; +import com.intellij.psi.impl.source.tree.CompositeElement; +import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.Nullable; + +/** + * Encapsulates implementation of + * {@link JavaWrapManager#arrangeChildWrap(ASTNode, ASTNode, CodeStyleSettings, Wrap, ReservedWrapsProvider)}. + *

+ * Thread-safe. + * + * @author Denis Zhdanov + * @since Apr 21, 2010 2:30:29 PM + */ +public class JavaChildWrapArranger { + + /** + * Provides implementation of {@link JavaWrapManager#arrangeChildWrap(ASTNode, ASTNode, CodeStyleSettings, Wrap, ReservedWrapsProvider)} + * method. + * + * @param child child node which {@link Wrap wrap} is to be defined + * @param parent direct or indirect parent of the given 'child' node. Defines usage context + * of 'child' node processing + * @param settings code style settings to use during wrap definition + * @param suggestedWrap wrap suggested to use by clients of current class. I.e. those clients offer wrap to + * use based on their information about current processing state. However, it's possible + * that they don't know details of fine-grained wrap definition algorithm encapsulated + * at the current class. Hence, this method takes suggested wrap into consideration but + * is not required to use it all the time node based on the given parameters + * @param reservedWrapsProvider reserved {@code 'element type -> wrap instance'} mappings provider. Note: this + * argument is considered to be a part of legacy heritage and is intended to be removed as + * soon as formatting code refactoring is done + * @return wrap to use for the given 'child' node if it's possible to define the one; + * null otherwise + */ + @SuppressWarnings({"MethodMayBeStatic"}) + @Nullable + public Wrap arrange(ASTNode child, ASTNode parent, CodeStyleSettings settings, Wrap suggestedWrap, + ReservedWrapsProvider reservedWrapsProvider) + { + final ASTNode directParent = child.getTreeParent(); + int role = ((CompositeElement)directParent).getChildRole(child); + final IElementType nodeType = parent.getElementType(); + if (nodeType == JavaElementType.BINARY_EXPRESSION) { + if (role == ChildRole.OPERATION_SIGN && !settings.BINARY_OPERATION_SIGN_ON_NEXT_LINE) return null; + if (role == ChildRole.ROPERAND && settings.BINARY_OPERATION_SIGN_ON_NEXT_LINE) return null; + return suggestedWrap; + } + final IElementType childType = child.getElementType(); + if (childType == JavaElementType.EXTENDS_LIST || childType == JavaElementType.IMPLEMENTS_LIST) { + return Wrap.createWrap(settings.EXTENDS_KEYWORD_WRAP, true); + } + else if (childType == JavaElementType.THROWS_LIST) { + return Wrap.createWrap(settings.THROWS_KEYWORD_WRAP, true); + } + else if (nodeType == JavaElementType.EXTENDS_LIST || nodeType == JavaElementType.IMPLEMENTS_LIST) { + if (role == ChildRole.REFERENCE_IN_LIST) { + return suggestedWrap; + } + else { + return null; + } + } + else if (nodeType == JavaElementType.THROWS_LIST) { + if (role == ChildRole.REFERENCE_IN_LIST) { + return suggestedWrap; + } + else { + return null; + } + } + else if (nodeType == JavaElementType.CONDITIONAL_EXPRESSION) { + if (role == ChildRole.COLON && !settings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null; + if (role == ChildRole.QUEST && !settings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null; + if (role == ChildRole.THEN_EXPRESSION && settings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null; + if (role == ChildRole.ELSE_EXPRESSION && settings.TERNARY_OPERATION_SIGNS_ON_NEXT_LINE) return null; + return suggestedWrap; + + } + + else if (FormattingAstUtil.isAssignment(parent)) { + if (role == ChildRole.INITIALIZER_EQ && settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return suggestedWrap; + if (role == ChildRole.INITIALIZER_EQ && !settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null; + if (role == ChildRole.OPERATION_SIGN && settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return suggestedWrap; + if (role == ChildRole.OPERATION_SIGN && !settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null; + if (role == ChildRole.INITIALIZER && !settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return suggestedWrap; + if (role == ChildRole.INITIALIZER && settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null; + if (role == ChildRole.ROPERAND && !settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return suggestedWrap; + if (role == ChildRole.ROPERAND && settings.PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE) return null; + if (role == ChildRole.CLOSING_SEMICOLON) return null; + //if (role == ChildRole.TYPE) return suggestedWrap; + return suggestedWrap; + } + + else if (nodeType == JavaElementType.REFERENCE_EXPRESSION) { + if (role == ChildRole.DOT) { + return reservedWrapsProvider.getReservedWrap(JavaElementType.REFERENCE_EXPRESSION); + } + else { + return suggestedWrap; + } + } + else if (nodeType == JavaElementType.FOR_STATEMENT) { + if (role == ChildRole.FOR_INITIALIZATION || role == ChildRole.CONDITION || role == ChildRole.FOR_UPDATE) { + return suggestedWrap; + } + if (role == ChildRole.LOOP_BODY) { + final boolean dontWrap = (childType == JavaElementType.CODE_BLOCK || childType == JavaElementType.BLOCK_STATEMENT) && + settings.BRACE_STYLE == CodeStyleSettings.END_OF_LINE; + return Wrap.createWrap(dontWrap ? WrapType.NONE : WrapType.NORMAL, true); + } + else { + return null; + } + + } + + else if (nodeType == JavaElementType.METHOD) { + if (role == ChildRole.THROWS_LIST) { + return suggestedWrap; + } + else { + return null; + } + } + + else if (nodeType == JavaElementType.MODIFIER_LIST) { + if (childType == JavaElementType.ANNOTATION) { + return reservedWrapsProvider.getReservedWrap(JavaElementType.MODIFIER_LIST); + } + ASTNode prevElement = FormattingAstUtil.getPrevElement(child); + if (prevElement != null && prevElement.getElementType() == JavaElementType.ANNOTATION) { + return reservedWrapsProvider.getReservedWrap(JavaElementType.MODIFIER_LIST); + } + else { + return null; + } + } + else if (nodeType == JavaElementType.ASSERT_STATEMENT) { + if (role == ChildRole.CONDITION) { + return suggestedWrap; + } + if (role == ChildRole.ASSERT_DESCRIPTION && !settings.ASSERT_STATEMENT_COLON_ON_NEXT_LINE) { + return suggestedWrap; + } + if (role == ChildRole.COLON && settings.ASSERT_STATEMENT_COLON_ON_NEXT_LINE) { + return suggestedWrap; + } + return null; + } + else if (nodeType == JavaElementType.CODE_BLOCK) { + if (role == ChildRole.STATEMENT_IN_BLOCK) { + return suggestedWrap; + } + else { + return null; + } + } + + else if (nodeType == JavaElementType.IF_STATEMENT) { + if (childType == JavaElementType.IF_STATEMENT && role == ChildRole.ELSE_BRANCH && settings.SPECIAL_ELSE_IF_TREATMENT) { + return Wrap.createWrap(WrapType.NONE, false); + } + if (role == ChildRole.THEN_BRANCH || role == ChildRole.ELSE_BRANCH) { + if (childType == JavaElementType.BLOCK_STATEMENT) { + return null; + } + else { + return Wrap.createWrap(WrapType.NORMAL, true); + } + } + } + + else if (nodeType == JavaElementType.FOREACH_STATEMENT || nodeType == JavaElementType.WHILE_STATEMENT) { + if (role == ChildRole.LOOP_BODY) { + if (childType == JavaElementType.BLOCK_STATEMENT) { + return null; + } + else { + return Wrap.createWrap(WrapType.NORMAL, true); + } + } + } + + else if (nodeType == JavaElementType.DO_WHILE_STATEMENT) { + if (role == ChildRole.LOOP_BODY) { + return Wrap.createWrap(WrapType.NORMAL, true); + } else if (role == ChildRole.WHILE_KEYWORD) { + return Wrap.createWrap(WrapType.NORMAL, true); + } + } else if (nodeType == JavaElementType.ANNOTATION_ARRAY_INITIALIZER) { + if (suggestedWrap != null) { + return suggestedWrap; + } + if (role == ChildRole.ANNOTATION_VALUE) { + return Wrap.createWrap(WrapType.NORMAL, true); + } + } + + return suggestedWrap; + } +} From 19444c3656577d06c9eb2faddd447af319bc17bf Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 22 Apr 2010 16:57:57 +0400 Subject: [PATCH 31/45] xdebugger: asynchronous fetching full value text --- .../frame/ImmediateFullValueEvaluator.java | 35 +++++++++++++ .../xdebugger/frame/XFullValueEvaluator.java | 52 +++++++++++++++++++ .../xdebugger/frame/XValueModifier.java | 2 +- .../intellij/xdebugger/frame/XValueNode.java | 7 ++- .../impl/evaluate/quick/XValueHint.java | 3 +- .../xdebugger/impl/ui/DebuggerUIUtil.java | 42 ++++++++++++--- .../impl/ui/tree/nodes/XValueNodeImpl.java | 18 +++---- 7 files changed, 134 insertions(+), 25 deletions(-) create mode 100644 platform/xdebugger-api/src/com/intellij/xdebugger/frame/ImmediateFullValueEvaluator.java create mode 100644 platform/xdebugger-api/src/com/intellij/xdebugger/frame/XFullValueEvaluator.java diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/ImmediateFullValueEvaluator.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/ImmediateFullValueEvaluator.java new file mode 100644 index 000000000000..0fc3366e35cc --- /dev/null +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/ImmediateFullValueEvaluator.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2010 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.xdebugger.frame; + +import org.jetbrains.annotations.NotNull; + +/** + * @author nik + */ +public class ImmediateFullValueEvaluator extends XFullValueEvaluator { + private String myFullValue; + + public ImmediateFullValueEvaluator(@NotNull String linkText, @NotNull String fullValue) { + super(linkText); + myFullValue = fullValue; + } + + @Override + public void startEvaluation(@NotNull XFullValueEvaluationCallback callback) { + callback.evaluated(myFullValue); + } +} diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XFullValueEvaluator.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XFullValueEvaluator.java new file mode 100644 index 000000000000..0c5483a1b5f0 --- /dev/null +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XFullValueEvaluator.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2010 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.xdebugger.frame; + +import org.jetbrains.annotations.NotNull; + +/** + * Supports asynchronous fetching full text of a value. If full text is already computed use {@link ImmediateFullValueEvaluator} + * @see XValueNode#setFullValueEvaluator + * @see ImmediateFullValueEvaluator + * + * @author nik + */ +public abstract class XFullValueEvaluator { + private String myLinkText; + + /** + * @param linkText text of the link what will be appended to a variables tree node text + */ + protected XFullValueEvaluator(@NotNull String linkText) { + myLinkText = linkText; + } + + /** + * Start fetching full text of the value. Note that this method is called from the Event Dispatch Thread so it should return quickly + * @param callback used to notify that the full text has been successfully evaluated or an error occurs + */ + public abstract void startEvaluation(@NotNull XFullValueEvaluationCallback callback); + + public String getLinkText() { + return myLinkText; + } + + public interface XFullValueEvaluationCallback { + void evaluated(@NotNull String fullValue); + + void errorOccurred(@NotNull String errorMessage); + } +} diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueModifier.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueModifier.java index e4f90b8fa1a6..d7889e7e9efc 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueModifier.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueModifier.java @@ -24,7 +24,7 @@ import org.jetbrains.annotations.Nullable; public abstract class XValueModifier { /** - * Start modification of the value. Note that this methods is called from the Event Dispatch Thread so it should return quickly + * Start modification of the value. Note that this method is called from the Event Dispatch Thread so it should return quickly * @param expression new value * @param callback used to notify that value has been successfully modified or an error occurs */ diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueNode.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueNode.java index de922b904dc5..941ae65c7f75 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueNode.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueNode.java @@ -38,9 +38,8 @@ public interface XValueNode extends Obsolescent { /** * If string representation of the value is too long to show in the tree pass truncated value to {@link #setPresentation(String, javax.swing.Icon, String, String, boolean)} * method and call this method to provide full value. - * This will add a link to the node and show fullValue text if a user click on that link. - * @param fullValue full text of the value. Will be shown in popup window - * @param linkText text of the link. Will be appended to the node text + * This will add a link to the node and show popup with full value if an user clicks on that link. + * @param fullValueEvaluator will be used to obtain full text of the value */ - void setFullValue(@NotNull String fullValue, @NotNull String linkText); + void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java index 4a6ceb994bf5..8797bde9ef4c 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java @@ -30,6 +30,7 @@ import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerUtil; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; +import com.intellij.xdebugger.frame.XFullValueEvaluator; import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.frame.XValueNode; import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint; @@ -90,7 +91,7 @@ public class XValueHint extends AbstractValueHint { }); } - public void setFullValue(@NotNull String fullValue, @NotNull String linkText) { + public void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator) { //todo[nik] implement? } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java index 0e161a49bb30..c4272f80b0f7 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java @@ -25,6 +25,7 @@ import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.wm.WindowManager; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.awt.RelativePoint; +import com.intellij.xdebugger.frame.XFullValueEvaluator; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -90,26 +91,51 @@ public class DebuggerUIUtil { return new RelativePoint(editor.getContentComponent(), p); } - public static void showValuePopup(@NotNull String text, @NotNull MouseEvent event, @NotNull Project project) { - JTextArea textArea = new JTextArea(text); + public static void showValuePopup(@NotNull XFullValueEvaluator text, @NotNull MouseEvent event, @NotNull Project project) { + final JTextArea textArea = new JTextArea("Evaluating..."); + text.startEvaluation(new FullValueEvaluationCallbackImpl(textArea)); + textArea.setEditable(false); textArea.setBackground(HintUtil.INFORMATION_COLOR); textArea.setLineWrap(false); final JScrollPane component = ScrollPaneFactory.createScrollPane(textArea); + final Dimension frameSize = WindowManager.getInstance().getFrame(project).getSize(); + final Dimension size = new Dimension(frameSize.width / 2, frameSize.height / 2); + component.setPreferredSize(size); component.setBorder(null); final JBPopup popup = JBPopupFactory.getInstance().createComponentPopupBuilder(component, null) .setResizable(true) .setMovable(true) + .setDimensionServiceKey(project, "XDebugger.FullValuePopup", false) .setRequestFocus(false) .createPopup(); - - final Dimension size = textArea.getPreferredSize(); final Component parentComponent = event.getComponent(); - final Dimension frameSize = WindowManager.getInstance().getFrame(project).getSize(); - size.width = Math.min(size.width, frameSize.width / 2); - size.height = Math.min(size.height, frameSize.height / 2); - component.setPreferredSize(size); RelativePoint point = new RelativePoint(parentComponent, new Point(event.getX()-size.width, event.getY()-size.height)); popup.show(point); } + + private static class FullValueEvaluationCallbackImpl implements XFullValueEvaluator.XFullValueEvaluationCallback { + private final JTextArea myTextArea; + + public FullValueEvaluationCallbackImpl(JTextArea textArea) { + myTextArea = textArea; + } + + public void evaluated(@NotNull final String fullValue) { + invokeOnEventDispatch(new Runnable() { + public void run() { + myTextArea.setText(fullValue); + } + }); + } + + public void errorOccurred(@NotNull final String errorMessage) { + invokeOnEventDispatch(new Runnable() { + public void run() { + myTextArea.setForeground(XDebuggerUIConstants.ERROR_MESSAGE_ATTRIBUTES.getFgColor()); + myTextArea.setText(errorMessage); + } + }); + } + } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java index 98578803c47a..f21546849afe 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java @@ -20,6 +20,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.StringBuilderSpinAllocator; import com.intellij.xdebugger.frame.XCompositeNode; +import com.intellij.xdebugger.frame.XFullValueEvaluator; import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.frame.XValueNode; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; @@ -39,10 +40,9 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu private String myName; private String myType; private String myValue; - private String myFullValue; + private XFullValueEvaluator myFullValueEvaluator; private String mySeparator; private boolean myChanged; - private String myLinkText; public XValueNodeImpl(XDebuggerTree tree, final XDebuggerTreeNode parent, final XValue value) { super(tree, parent, value); @@ -74,11 +74,10 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu }); } - public void setFullValue(@NotNull final String fullValue, @NotNull final String linkText) { + public void setFullValueEvaluator(@NotNull final XFullValueEvaluator fullValueEvaluator) { DebuggerUIUtil.invokeOnEventDispatch(new Runnable() { public void run() { - myLinkText = linkText; - myFullValue = fullValue; + myFullValueEvaluator = fullValueEvaluator; fireNodeChanged(); } }); @@ -122,11 +121,11 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu @Override public XDebuggerNodeLink getLink() { - if (myFullValue != null) { - return new XDebuggerNodeLink(myLinkText) { + if (myFullValueEvaluator != null) { + return new XDebuggerNodeLink(myFullValueEvaluator.getLinkText()) { @Override public void onClick(MouseEvent event) { - DebuggerUIUtil.showValuePopup(myFullValue, event, myTree.getProject()); + DebuggerUIUtil.showValuePopup(myFullValueEvaluator, event, myTree.getProject()); } }; } @@ -135,9 +134,6 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu @Nullable public String getValue() { - if (myFullValue != null) { - return myFullValue; - } return myValue; } From 9a13cb9aee10df364a8fcf000b261102eff50587 Mon Sep 17 00:00:00 2001 From: Roman Chernyatchik Date: Thu, 22 Apr 2010 14:43:59 +0400 Subject: [PATCH 32/45] cosmetics --- .../execution/process/CommandLineArgumentsProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/execution/process/CommandLineArgumentsProvider.java b/platform/platform-api/src/com/intellij/execution/process/CommandLineArgumentsProvider.java index e0f2d9cd622c..68d99ba6bb54 100644 --- a/platform/platform-api/src/com/intellij/execution/process/CommandLineArgumentsProvider.java +++ b/platform/platform-api/src/com/intellij/execution/process/CommandLineArgumentsProvider.java @@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Map; /** - * @author oleg + * @author Roman.Chernyatchik, oleg */ public interface CommandLineArgumentsProvider { /** From 06424d4332343ded566d5f9a28f900ac18d20abb Mon Sep 17 00:00:00 2001 From: "Rustam.Vishnyakov" Date: Thu, 22 Apr 2010 17:23:55 +0400 Subject: [PATCH 33/45] Merged from 9.0.x (Maia) branch --- .../intellij/psi/formatter/FormatterUtil.java | 20 ++++++ .../intellij/psi/formatter/WrappingUtil.java | 72 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 platform/lang-impl/src/com/intellij/psi/formatter/WrappingUtil.java diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java b/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java index ccd6e4f7db62..b405b0ebbb00 100644 --- a/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java @@ -19,10 +19,12 @@ import com.intellij.lang.ASTFactory; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.TokenType; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import com.intellij.util.CharTable; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nullable; @@ -248,4 +250,22 @@ public class FormatterUtil { return true; } + public static boolean isPrecededBy(ASTNode node, IElementType eType) { + ASTNode prevNode = node.getTreePrev(); + while (prevNode != null && prevNode.getPsi() instanceof PsiWhiteSpace) { + prevNode = prevNode.getTreePrev(); + } + if (prevNode == null) return false; + return prevNode.getElementType() == eType; + } + + public static boolean isPrecededBy(ASTNode node, TokenSet tokens) { + ASTNode prevNode = node.getTreePrev(); + while (prevNode != null && prevNode.getPsi() instanceof PsiWhiteSpace) { + prevNode = prevNode.getTreePrev(); + } + if (prevNode == null) return false; + return tokens.contains(prevNode.getElementType()); + } + } diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/WrappingUtil.java b/platform/lang-impl/src/com/intellij/psi/formatter/WrappingUtil.java new file mode 100644 index 000000000000..bfc480c5f688 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/psi/formatter/WrappingUtil.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2010 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.formatter; + +import com.intellij.formatting.Wrap; +import com.intellij.formatting.WrapType; +import com.intellij.lang.ASTNode; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.tree.IElementType; + +/** + * Misc. code wrapping functions + * @author rvishnyakov + */ +public class WrappingUtil { + + private WrappingUtil() { + } + + public static boolean shouldWrap(int setting) { + return setting != CodeStyleSettings.DO_NOT_WRAP; + } + + public static Wrap createWrap(int setting) { + return Wrap.createWrap(getWrapType(setting), true); + } + + public static WrapType getWrapType(int setting) { + switch (setting) { + case CodeStyleSettings.WRAP_ALWAYS: + return WrapType.ALWAYS; + case CodeStyleSettings.WRAP_AS_NEEDED: + return WrapType.NORMAL; + case CodeStyleSettings.DO_NOT_WRAP: + return WrapType.NONE; + default: + return WrapType.CHOP_DOWN_IF_LONG; + } + } + + public static WrapType getArrayInitializerWrapType(CodeStyleSettings settings, + ASTNode node, + IElementType lBraceType, + IElementType rBraceType) { + WrapType wrapType = WrapType.NONE; + if (shouldWrap(settings.ARRAY_INITIALIZER_WRAP)) { + if (node.getElementType() == rBraceType) { + wrapType = settings.ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE ? Wrap.ALWAYS : Wrap.NONE; + } + else if (FormatterUtil.isPrecededBy(node, lBraceType)) { + wrapType = settings.ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE ? Wrap.ALWAYS : Wrap.NONE; + } + else { + wrapType = WrappingUtil.getWrapType(settings.ARRAY_INITIALIZER_WRAP); + } + } + return wrapType; + } +} From aeb1872f2cd2cf3c537a9370558414d80a014343 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 22 Apr 2010 17:42:31 +0400 Subject: [PATCH 34/45] fix 'square' symbols in framework support wizard dialog --- platform/platform-api/src/com/intellij/ui/GuiUtils.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/ui/GuiUtils.java b/platform/platform-api/src/com/intellij/ui/GuiUtils.java index ff7db4427a67..8a6a90c84908 100644 --- a/platform/platform-api/src/com/intellij/ui/GuiUtils.java +++ b/platform/platform-api/src/com/intellij/ui/GuiUtils.java @@ -24,6 +24,7 @@ import com.intellij.openapi.ui.FixedSizeButton; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.CharFilter; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -50,6 +51,11 @@ public class GuiUtils { private static final Insets paddingInsideDialog = new Insets(5, 5, 5, 5); public static final int lengthForFileField = 25; + private static final CharFilter NOT_MNEMONIC_CHAR_FILTER = new CharFilter() { + public boolean accept(char ch) { + return ch != '&' && ch != UIUtil.MNEMONIC; + } + }; public static JPanel constructFieldWithBrowseButton(JComponent aComponent, ActionListener aActionListener) { return constructFieldWithBrowseButton(aComponent, aActionListener, 0); @@ -187,7 +193,7 @@ public class GuiUtils { } public static String getTextWithoutMnemonicEscaping(String text) { - return text.replaceAll("&", ""); + return StringUtil.strip(text, NOT_MNEMONIC_CHAR_FILTER); } public static char getDisplayedMnemonic(String text) { From a4191ba2513e5a9b4a0ecf4b9c82e23e45b13668 Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Thu, 22 Apr 2010 17:52:41 +0400 Subject: [PATCH 35/45] fix keymap test --- .../platform-resources/src/idea/Keymap_Eclipse.xml | 10 ++-------- platform/platform-resources/src/idea/Keymap_Emacs.xml | 2 +- platform/platform-resources/src/idea/Keymap_KDE.xml | 2 +- .../platform-resources/src/idea/Keymap_Netbeans.xml | 10 +++------- 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/platform/platform-resources/src/idea/Keymap_Eclipse.xml b/platform/platform-resources/src/idea/Keymap_Eclipse.xml index de8626efc763..6108e7648f1a 100644 --- a/platform/platform-resources/src/idea/Keymap_Eclipse.xml +++ b/platform/platform-resources/src/idea/Keymap_Eclipse.xml @@ -22,19 +22,13 @@ - - - - + - - - - + diff --git a/platform/platform-resources/src/idea/Keymap_Emacs.xml b/platform/platform-resources/src/idea/Keymap_Emacs.xml index bd928b8b397a..7025ec286e34 100644 --- a/platform/platform-resources/src/idea/Keymap_Emacs.xml +++ b/platform/platform-resources/src/idea/Keymap_Emacs.xml @@ -224,7 +224,7 @@ - + diff --git a/platform/platform-resources/src/idea/Keymap_KDE.xml b/platform/platform-resources/src/idea/Keymap_KDE.xml index 377d5c094ff6..0751bed27d80 100644 --- a/platform/platform-resources/src/idea/Keymap_KDE.xml +++ b/platform/platform-resources/src/idea/Keymap_KDE.xml @@ -6,7 +6,7 @@ - + diff --git a/platform/platform-resources/src/idea/Keymap_Netbeans.xml b/platform/platform-resources/src/idea/Keymap_Netbeans.xml index 93095e74205f..024c60ceed38 100644 --- a/platform/platform-resources/src/idea/Keymap_Netbeans.xml +++ b/platform/platform-resources/src/idea/Keymap_Netbeans.xml @@ -42,20 +42,16 @@ - - - + - + - - - + From ed51f81a4b2b745e8a9fd743da07b3cd4151aeec Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 22 Apr 2010 17:55:03 +0400 Subject: [PATCH 36/45] IDEA-43962 Indentation error on deep nesting levels 1. Test is added; 2. Minor code reformatting; --- .../psi/formatter/JavaFormatterTest.java | 59 ++++++++++++++----- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/JavaFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/JavaFormatterTest.java index 170bee46703c..e92029d04377 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/JavaFormatterTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/JavaFormatterTest.java @@ -2,7 +2,6 @@ package com.intellij.psi.formatter; import com.intellij.JavaTestUtil; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.EditorFactory; @@ -35,7 +34,6 @@ public class JavaFormatterTest extends LightIdeaTestCase { doTest("SCR915.java", "SCR915_after.java"); } - public void testForEach() throws Exception { doTest("ForEach.java", "ForEach_after.java"); } @@ -208,6 +206,35 @@ public class JavaFormatterTest extends LightIdeaTestCase { doTest(); } + public void testNestedMethodsIndentation() throws Exception { + // Inspired by IDEA-43962 + + getSettings().getIndentOptions(StdFileTypes.JAVA).CONTINUATION_INDENT_SIZE = 4; + + doMethodTest( + "BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + ".add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE)))))))));", + "BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE\n" + + " .add(BigDecimal.ONE)))))))));" + ); + } + public void testSwitch() throws Exception { doTest(); } @@ -2893,22 +2920,26 @@ public class JavaFormatterTest extends LightIdeaTestCase { getSettings().ARRAY_INITIALIZER_WRAP = CodeStyleSettings.WRAP_ALWAYS; getSettings().ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE = true; getSettings().ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE = true; - doTextTest("public @interface Ann\n" + + doTextTest( + "public @interface Ann\n" + "{\n" + "int[] x = { 1, 2 };\n" + "\n" + "Mode[] modes () default { @Mode(value = 1), @Mode(value = 2) };\n" + - "}", "public @interface Ann {\n" + - " int[] x = {\n" + - " 1,\n" + - " 2\n" + - " };\n" + - "\n" + - " Mode[] modes() default {\n" + - " @Mode(value = 1),\n" + - " @Mode(value = 2)\n" + - " };\n" + - "}"); + "}", + + "public @interface Ann {\n" + + " int[] x = {\n" + + " 1,\n" + + " 2\n" + + " };\n" + + "\n" + + " Mode[] modes() default {\n" + + " @Mode(value = 1),\n" + + " @Mode(value = 2)\n" + + " };\n" + + "}" + ); } private void doMethodTest(final String before, final String after) throws Exception { From 6a80949468150b97bdd88dd3327b635733614d85 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 22 Apr 2010 18:30:43 +0400 Subject: [PATCH 37/45] misc optimizations for showing lookup with many elements: - using ContainerUtil.toArray - cheaper checks of relevance to Java-specific weighers - avoid expensive Class#isInstanceOf of LookupElement#as using: * LookupItem#from with explicit instanceof LookupItem (caring of LookupElementDecorator) * isCaseSensitive introduced to LookupElement --- .../completion/JavaCompletionStatistician.java | 2 +- .../codeInsight/completion/JavaCompletionUtil.java | 3 +-- .../codeInsight/completion/StaticMembersWeigher.java | 7 ++++--- .../psi/util/proximity/JavaInheritanceWeigher.java | 8 +++++--- .../intellij/codeInsight/lookup/LookupElement.java | 4 ++++ .../codeInsight/lookup/LookupElementDecorator.java | 4 ++++ .../src/com/intellij/psi/WeighingService.java | 3 ++- .../completion/impl/CamelHumpMatcher.java | 9 +-------- .../com/intellij/codeInsight/lookup/LookupItem.java | 12 ++++++++++++ 9 files changed, 34 insertions(+), 18 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionStatistician.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionStatistician.java index 3897e6bf60a9..53c086b921ae 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionStatistician.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionStatistician.java @@ -51,7 +51,7 @@ public class JavaCompletionStatistician extends CompletionStatistician{ } } - LookupItem item = element.as(LookupItem.class); + LookupItem item = LookupItem.from(element); if (item == null) return null; PsiType qualifierType = JavaCompletionUtil.getQualifierType(item); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 5d117e06d698..f1e4c57abf95 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -789,9 +789,8 @@ public class JavaCompletionUtil { return typed.getType(); } - final PsiType qualifierType = getPsiType(element.getObject()); - final LookupItem lookupItem = element.as(LookupItem.class); + final LookupItem lookupItem = LookupItem.from(element); if (lookupItem != null) { final Object o = lookupItem.getAttribute(LookupItem.TYPE); if (o instanceof PsiType) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/StaticMembersWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/StaticMembersWeigher.java index 6cd3ff7dc0b8..d6c57c7b8ed1 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/StaticMembersWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/StaticMembersWeigher.java @@ -31,6 +31,10 @@ public class StaticMembersWeigher extends CompletionWeigher { final PsiElement position = loc.getCompletionParameters().getPosition(); if (!position.isValid()) return 0; + // cheap weigher applicability goes first + final Object o = element.getObject(); + if (!(o instanceof PsiMember)) return 0; + if (PsiTreeUtil.getParentOfType(position, PsiDocComment.class) != null) return 0; if (position.getParent() instanceof PsiReferenceExpression) { final PsiReferenceExpression refExpr = (PsiReferenceExpression)position.getParent(); @@ -43,9 +47,6 @@ public class StaticMembersWeigher extends CompletionWeigher { } } - final Object o = element.getObject(); - if (!(o instanceof PsiMember)) return 0; - if (((PsiMember)o).hasModifierProperty(PsiModifier.STATIC)) { if (o instanceof PsiMethod) return 5; if (o instanceof PsiField) return 4; diff --git a/java/java-impl/src/com/intellij/psi/util/proximity/JavaInheritanceWeigher.java b/java/java-impl/src/com/intellij/psi/util/proximity/JavaInheritanceWeigher.java index 227cc74a2809..ac39286e7063 100644 --- a/java/java-impl/src/com/intellij/psi/util/proximity/JavaInheritanceWeigher.java +++ b/java/java-impl/src/com/intellij/psi/util/proximity/JavaInheritanceWeigher.java @@ -28,6 +28,9 @@ import org.jetbrains.annotations.Nullable; public class JavaInheritanceWeigher extends ProximityWeigher { public Comparable weigh(@NotNull final PsiElement element, final ProximityLocation location) { + if (element instanceof PsiClass && isTooGeneral((PsiClass)element)) return false; + if (element instanceof PsiMethod && isTooGeneral(((PsiMethod)element).getContainingClass())) return false; + final PsiElement position = location.getPosition(); PsiClass placeClass = PsiTreeUtil.getContextOfType(element, PsiClass.class, false); if (position.getParent() instanceof PsiReferenceExpression) { @@ -43,9 +46,8 @@ public class JavaInheritanceWeigher extends ProximityWeigher { } } - if (element instanceof PsiClass && isTooGeneral((PsiClass)element)) return false; - if (element instanceof PsiMethod && isTooGeneral(((PsiMethod)element).getContainingClass())) return false; - + if (placeClass == null) return false; + PsiClass contextClass = PsiTreeUtil.getContextOfType(position, PsiClass.class, false); while (contextClass != null) { PsiClass elementClass = placeClass; diff --git a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElement.java b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElement.java index 36551be199db..f347e1ad2674 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElement.java +++ b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElement.java @@ -78,4 +78,8 @@ public abstract class LookupElement extends UserDataHolderBase { //noinspection unchecked return aClass.isInstance(this) ? (T) this : null; } + + public boolean isCaseSensitive() { + return true; + } } diff --git a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementDecorator.java b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementDecorator.java index 83b49414f150..1aab873ff062 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementDecorator.java +++ b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementDecorator.java @@ -112,6 +112,10 @@ public abstract class LookupElementDecorator extends Lo final T t = super.as(aClass); return t == null ? myDelegate.as(aClass) : t; } + + public boolean isCaseSensitive() { + return myDelegate.isCaseSensitive(); + } private static class InsertingDecorator extends LookupElementDecorator { private final InsertHandler> myInsertHandler; diff --git a/platform/lang-api/src/com/intellij/psi/WeighingService.java b/platform/lang-api/src/com/intellij/psi/WeighingService.java index 7fd0b33cd2fe..4a685e76a11a 100644 --- a/platform/lang-api/src/com/intellij/psi/WeighingService.java +++ b/platform/lang-api/src/com/intellij/psi/WeighingService.java @@ -17,6 +17,7 @@ package com.intellij.psi; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.KeyedExtensionCollector; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -37,7 +38,7 @@ public class WeighingService { @NotNull public static WeighingComparable weigh(Key> key, T element, Loc location) { final List weighers = COLLECTOR.forKey(key); - return new WeighingComparable(element, location, weighers.toArray(new Weigher[weighers.size()])); + return new WeighingComparable(element, location, ContainerUtil.toArray(weighers, new Weigher[weighers.size()])); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java index 1da6c1810f49..8c06d094e91e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java @@ -7,8 +7,6 @@ package com.intellij.codeInsight.completion.impl; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.completion.PrefixMatcher; import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.codeStyle.NameUtil; import com.intellij.util.containers.hash.LinkedHashMap; @@ -62,12 +60,7 @@ public class CamelHumpMatcher extends PrefixMatcher { public boolean prefixMatches(@NotNull final LookupElement element) { - final LookupItem item = element.as(LookupItem.class); //must die, use LookupElementBuilder or CompletionResultSet.caseInsensitive - final LookupElementBuilder builder = element.as(LookupElementBuilder.class); - boolean itemCaseInsensitive = item != null && Boolean.TRUE.equals(item.getAttribute(LookupItem.CASE_INSENSITIVE)) || - builder != null && !builder.isCaseSensitive(); - - return prefixMatchersInternal(element, itemCaseInsensitive); + return prefixMatchersInternal(element, !element.isCaseSensitive()); } private boolean prefixMatchersInternal(final LookupElement element, final boolean itemCaseInsensitive) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupItem.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupItem.java index a1337eb12f77..27c3d885c1fa 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupItem.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupItem.java @@ -359,4 +359,16 @@ public class LookupItem extends MutableLookupElement implements Comparable myAttributes.putAll(item.myAttributes); } + @Override + public boolean isCaseSensitive() { + return !Boolean.TRUE.equals(getAttribute(CASE_INSENSITIVE)); + } + + public static @Nullable LookupItem from(LookupElement lookupElement) { + if (lookupElement instanceof LookupElementDecorator) { + lookupElement = ((LookupElementDecorator)lookupElement).getDelegate(); + } + if (lookupElement instanceof LookupItem) return (LookupItem)lookupElement; + return null; + } } From 65784c27fbd98a2f363c93f2b4ccb2cffeed9ed4 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Thu, 22 Apr 2010 18:41:28 +0400 Subject: [PATCH 38/45] servlets ui --- java/java-impl/src/com/intellij/psi/util/CreateClassUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/java-impl/src/com/intellij/psi/util/CreateClassUtil.java b/java/java-impl/src/com/intellij/psi/util/CreateClassUtil.java index 1aa835653d85..3bc00b656274 100644 --- a/java/java-impl/src/com/intellij/psi/util/CreateClassUtil.java +++ b/java/java-impl/src/com/intellij/psi/util/CreateClassUtil.java @@ -91,6 +91,7 @@ public class CreateClassUtil { else { final FileTemplateManager fileTemplateManager = FileTemplateManager.getInstance(); FileTemplate fileTemplate = fileTemplateManager.getJ2eeTemplate(templateName); + LOG.assertTrue(fileTemplate != null, templateName + " not found"); final String text = fileTemplate.getText(attributes); aClass = JavaCreateFromTemplateHandler.createClassOrInterface(project, directory, text, true, fileTemplate.getExtension()); } From 51dd78ddcf01e17bad7a1a296afb63c91c2c19e1 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 22 Apr 2010 20:35:22 +0400 Subject: [PATCH 39/45] proper quick doc pop placement on second and subsequent invokations (when changing selected item in completion lookup with autopopup quickdoc option on) --- .../codeInsight/documentation/DocumentationManager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index 8e73be8d15a1..c762b8c32109 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -316,6 +316,12 @@ public class DocumentationManager { component.setHint(hint); + if (myEditor == null) { + // subsequent invocation of javadoc popup from completion will have myEditor == null because of cancel invoked, + // so reevaluate the editor for proper popup placement + Lookup lookup = LookupManager.getInstance(myProject).getActiveLookup(); + myEditor = lookup != null ? lookup.getEditor() : null; + } fetchDocInfo(getDefaultCollector(element, originalElement), component); myDocInfoHintRef = new WeakReference(hint); From 88c0e1289da3880a822764d78184955185922ccf Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 22 Apr 2010 13:08:12 +0400 Subject: [PATCH 40/45] -> community --- .../javadoc/JavaDocInfoGeneratorTest.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java new file mode 100644 index 000000000000..e42f48f1c17a --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java @@ -0,0 +1,79 @@ +package com.intellij.codeInsight.javadoc; + +import com.intellij.JavaTestUtil; +import com.intellij.codeInsight.CodeInsightTestCase; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.testFramework.PsiTestUtil; + +import java.io.File; +import java.io.IOException; + +/** + * @author yole + */ +public class JavaDocInfoGeneratorTest extends CodeInsightTestCase { + public void testSimpleField() throws Exception { + doTestField(); + } + + public void testFieldValue() throws Exception { + doTestField(); + } + + public void testValueInMethod() throws Exception { + doTestMethod(); + } + + public void testIdeadev2326() throws Exception { + doTestMethod(); + } + + public void testMethodTypeParameter() throws Exception { + doTestMethod(); + } + + public void testClassTypeParameter() throws Exception { + verifyJavaDoc(getTestClass()); + } + + private void doTestField() throws Exception { + PsiClass psiClass = getTestClass(); + PsiField field = psiClass.getFields() [0]; + verifyJavaDoc(field); + } + + private void doTestMethod() throws Exception { + PsiClass psiClass = getTestClass(); + PsiMethod method = psiClass.getMethods() [0]; + verifyJavaDoc(method); + } + + private PsiClass getTestClass() throws Exception{ + configureByFile("/codeInsight/javadocIG/" + getTestName(true) + ".java"); + return ((PsiJavaFile)myFile).getClasses() [0]; + } + + private void verifyJavaDoc(final PsiElement field) throws IOException { + final File htmlPath = new File(JavaTestUtil.getJavaTestDataPath() + "/codeInsight/javadocIG/" + getTestName(true) + ".html"); + String htmlText = new String(FileUtil.loadFileText(htmlPath)); + String docInfo = new JavaDocInfoGenerator(getProject(), field).generateDocInfo(null); + assertEquals(StringUtil.convertLineSeparators(htmlText.trim()), StringUtil.convertLineSeparators(docInfo.trim())); + } + + public void testPackageInfo() throws Exception { + final String path = JavaTestUtil.getJavaTestDataPath() + "/codeInsight/javadocIG/"; + final String packageInfo = path + getTestName(true); + PsiTestUtil.createTestProjectStructure(myProject, myModule, path, myFilesToDelete); + final String info = + new JavaDocInfoGenerator(getProject(), JavaPsiFacade.getInstance(getProject()).findPackage(getTestName(true))).generateDocInfo(null); + String htmlText = new String(FileUtil.loadFileText(new File(packageInfo + File.separator + "packageInfo.html"))); + assertEquals(StringUtil.convertLineSeparators(htmlText.trim()), StringUtil.convertLineSeparators(info.trim())); + } + + @Override + protected String getTestDataPath() { + return JavaTestUtil.getJavaTestDataPath(); + } +} From e82558cb475f337983289e92567584a43446451c Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 22 Apr 2010 14:01:25 +0400 Subject: [PATCH 41/45] allow to move java files without classes, e.g. package-info.java ( IDEA-53558 ) --- .../moveClassesOrPackages/MoveJavaFileHandler.java | 14 ++++++++++++++ .../JavaMoveFilesOrDirectoriesHandler.java | 5 +++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaFileHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaFileHandler.java index 69264c50165a..ec5a3c00fcfa 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaFileHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveJavaFileHandler.java @@ -84,5 +84,19 @@ public class MoveJavaFileHandler extends MoveFileHandler { @Override public void updateMovedFile(PsiFile file) throws IncorrectOperationException { ChangeContextUtil.decodeContextInfo(file, null, null); + final PsiDirectory containingDirectory = file.getContainingDirectory(); + if (containingDirectory != null) { + final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(containingDirectory); + if (aPackage != null) { + final PsiPackageStatement packageStatement = + JavaPsiFacade.getElementFactory(file.getProject()).createPackageStatement(aPackage.getQualifiedName()); + if (file instanceof PsiJavaFile) { + final PsiPackageStatement filePackageStatement = ((PsiJavaFile)file).getPackageStatement(); + if (filePackageStatement != null) { + filePackageStatement.getPackageReference().replace(packageStatement.getPackageReference()); + } + } + } + } } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/JavaMoveFilesOrDirectoriesHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/JavaMoveFilesOrDirectoriesHandler.java index e114782b7c0f..f56925dfded3 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/JavaMoveFilesOrDirectoriesHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveFilesOrDirectories/JavaMoveFilesOrDirectoriesHandler.java @@ -33,7 +33,8 @@ public class JavaMoveFilesOrDirectoriesHandler extends MoveFilesOrDirectoriesHan allJava &= JavaCopyFilesOrDirectoriesHandler.hasPackages((PsiDirectory)element); } else if (element instanceof PsiFile) { - allJava &= element instanceof PsiJavaFile && !JspPsiUtil.isInJspFile(element) && !CollectHighlightsUtil.isOutsideSourceRootJavaFile((PsiJavaFile) element); + allJava &= element instanceof PsiJavaFile && !JspPsiUtil.isInJspFile(element) && + ((PsiJavaFile)element).getClasses().length > 0 && !CollectHighlightsUtil.isOutsideSourceRootJavaFile((PsiJavaFile) element); } else { return false; @@ -55,6 +56,6 @@ public class JavaMoveFilesOrDirectoriesHandler extends MoveFilesOrDirectoriesHan @Override public void doMove(Project project, PsiElement[] elements, PsiElement targetContainer, MoveCallback callback) { - super.doMove(project, elements, targetContainer, callback); //To change body of overridden methods use File | Settings | File Templates. + super.doMove(project, elements, targetContainer, callback); } } From eef8f4fb2548954e28f182fd486e3ca92239c7f1 Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 22 Apr 2010 16:57:01 +0400 Subject: [PATCH 42/45] javadoc signature: short name for nested classes fixed --- .../impl/source/javadoc/PsiDocMethodOrFieldRef.java | 13 ++++++++++++- .../javaDoc/InnerClassReferenceInSignature.java | 13 +++++++++++++ .../codeInsight/daemon/JavadocHighlightingTest.java | 2 ++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/InnerClassReferenceInSignature.java diff --git a/java/java-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java b/java/java-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java index 350ee4ee1644..4ba92eed93e4 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java @@ -30,6 +30,7 @@ import com.intellij.psi.scope.ElementClassFilter; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.scope.processor.FilterScopeProcessor; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.CharTable; @@ -112,7 +113,17 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo PsiParameter parameter = parameters[j]; PsiType type1 = TypeConversionUtil.erasure(parameter.getType()); String type2 = signature[j]; - if (!Comparing.strEqual(type1.getPresentableText(), type2) && !Comparing.strEqual(type1.getCanonicalText(), type2)) continue nextMethod; + if (!Comparing.strEqual(type1.getPresentableText(), type2) && !Comparing.strEqual(type1.getCanonicalText(), type2)) { + String shortName = ""; + PsiClass psiClass = PsiUtil.resolveClassInType(type1); + while (psiClass != null) { + shortName = psiClass.getName() + (shortName.length() > 0 ? "." + shortName : ""); + psiClass = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class); + } + if (!Comparing.strEqual(shortName, type2)) { + continue nextMethod; + } + } } return new MyReference(method) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/InnerClassReferenceInSignature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/InnerClassReferenceInSignature.java new file mode 100644 index 000000000000..9303071aab23 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/InnerClassReferenceInSignature.java @@ -0,0 +1,13 @@ +class CSS { + static class IO{} +} + +class TD { + void calculateSmth(CSS.IO io){} +} + +/** + * @see TD#calculateSmth(CSS.IO) + */ +class Test { +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java index b310a8812e1e..7f9dd579eca2 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java @@ -90,6 +90,8 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase { public void testVararg() throws Exception {doTest();} + public void testInnerClassReferenceInSignature() throws Exception {doTest();} + public void testBadReference() throws Exception{ doTest(); } From 35e09403887c23343f90a46d0c62adbbe01bdda9 Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 22 Apr 2010 17:53:11 +0400 Subject: [PATCH 43/45] show progress on process starting ( IDEA-51441 ) --- .../src/com/intellij/openapi/progress/util/ColorProgressBar.java | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ColorProgressBar.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ColorProgressBar.java index 1772ddeedce0..31743acc7005 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ColorProgressBar.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ColorProgressBar.java @@ -108,7 +108,6 @@ public class ColorProgressBar extends JComponent { protected void paintComponent(Graphics g) { super.paintComponent(g); - if (myFraction == 0) return; Graphics2D g2 = (Graphics2D)g; Object oldAntialiasing = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING); From b26810db0022a3e635bb33c7057bed4adb689b4d Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 22 Apr 2010 20:33:43 +0400 Subject: [PATCH 44/45] append "Jump to sources" (IDEA-41192) --- .../ModulesDependenciesPanel.java | 26 ++++++++++++++++++- .../packageDependencies/ui/ModuleNode.java | 16 ++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/moduleDependencies/ModulesDependenciesPanel.java b/platform/lang-impl/src/com/intellij/moduleDependencies/ModulesDependenciesPanel.java index 8a622b3883fb..76a8c28d14fb 100644 --- a/platform/lang-impl/src/com/intellij/moduleDependencies/ModulesDependenciesPanel.java +++ b/platform/lang-impl/src/com/intellij/moduleDependencies/ModulesDependenciesPanel.java @@ -33,8 +33,10 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootEvent; import com.intellij.openapi.roots.ModuleRootListener; +import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.util.IconLoader; +import com.intellij.pom.Navigatable; import com.intellij.ui.*; import com.intellij.ui.content.Content; import com.intellij.ui.treeStructure.Tree; @@ -352,6 +354,7 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen group.add(actionManager.createExpandAllAction(treeExpander, tree)); } group.add(actionManager.createCollapseAllAction(treeExpander, tree)); + group.add(ActionManager.getInstance().getAction(IdeActions.ACTION_EDIT_SOURCE)); group.add(ActionManager.getInstance().getAction(IdeActions.MODULE_SETTINGS)); appendDependenciesAction(group); return group; @@ -406,7 +409,7 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen TreeUtil.selectFirstNode(myLeftTree); } - private static class MyUserObject{ + private static class MyUserObject implements Navigatable{ private boolean myInCycle; private final Module myModule; @@ -438,6 +441,18 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen public String toString() { return myModule.getName(); } + + public void navigate(boolean requestFocus) { + ProjectSettingsService.getInstance(myModule.getProject()).openModuleSettings(myModule); + } + + public boolean canNavigate() { + return myModule != null && !myModule.isDisposed(); + } + + public boolean canNavigateToSource() { + return false; + } } private static class MyTreePanel extends JPanel implements DataProvider{ @@ -466,6 +481,15 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen if (PlatformDataKeys.HELP_ID.is(dataId)) { return ourHelpID; } + if (PlatformDataKeys.NAVIGATABLE.is(dataId)) { + final TreePath selectionPath = myTree.getLeadSelectionPath(); + if (selectionPath != null && selectionPath.getLastPathComponent() instanceof DefaultMutableTreeNode){ + DefaultMutableTreeNode node = (DefaultMutableTreeNode)selectionPath.getLastPathComponent(); + if (node.getUserObject() instanceof MyUserObject){ + return node.getUserObject(); + } + } + } return null; } } diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/ModuleNode.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/ModuleNode.java index 77aabfd07e16..d68e4068857f 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/ModuleNode.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/ModuleNode.java @@ -18,6 +18,7 @@ package com.intellij.packageDependencies.ui; import com.intellij.analysis.AnalysisScopeBundle; import com.intellij.openapi.module.Module; +import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService; import com.intellij.openapi.util.Comparing; import com.intellij.psi.PsiFile; @@ -40,6 +41,21 @@ public class ModuleNode extends PackageDependenciesNode { } } + @Override + public boolean canNavigate() { + return myModule != null && !myModule.isDisposed(); + } + + @Override + public boolean canNavigateToSource() { + return false; + } + + @Override + public void navigate(boolean focus) { + ProjectSettingsService.getInstance(myModule.getProject()).openModuleSettings(myModule); + } + public Icon getOpenIcon() { return myModule == null ? null : myModule.getModuleType().getNodeIcon(true); } From a26f7384ea7e5478938136310d3d8818faf71fa1 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 22 Apr 2010 20:40:50 +0400 Subject: [PATCH 45/45] LH: deadlock fixed --- .../com/intellij/history/core/ChangeList.java | 17 +++++++++ .../history/core/LocalHistoryFacade.java | 6 +++ .../LocalHistoryEventDispatcher.java | 37 ++++--------------- .../history/core/changes/ChangeListTest.java | 22 +++++++++++ 4 files changed, 53 insertions(+), 29 deletions(-) diff --git a/platform/lvcs-impl/src/com/intellij/history/core/ChangeList.java b/platform/lvcs-impl/src/com/intellij/history/core/ChangeList.java index f180a35105ee..da05e59f0626 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/ChangeList.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/ChangeList.java @@ -67,16 +67,33 @@ public class ChangeList { myChangeSetDepth++; if (myChangeSetDepth > 1) return; + doBeginChangeSet(); + } + + private void doBeginChangeSet() { myCurrentChangeSet = new ChangeSet(myStorage.nextId(), Clock.getCurrentTimestamp()); myCurrentBlock.add(myCurrentChangeSet); } + public synchronized boolean forceBeginChangeSet() { + boolean split = myChangeSetDepth > 0; + if (split) doEndChangeSet(null); + + myChangeSetDepth++; + doBeginChangeSet(); + return split; + } + public synchronized boolean endChangeSet(String name) { assert myChangeSetDepth > 0; myChangeSetDepth--; if (myChangeSetDepth > 0) return false; + return doEndChangeSet(name); + } + + private boolean doEndChangeSet(String name) { if (myCurrentChangeSet.getChanges().isEmpty()) { myCurrentBlock.removeLast(); return false; diff --git a/platform/lvcs-impl/src/com/intellij/history/core/LocalHistoryFacade.java b/platform/lvcs-impl/src/com/intellij/history/core/LocalHistoryFacade.java index e77ba8d53a6a..b39507cf2a9a 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/LocalHistoryFacade.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/LocalHistoryFacade.java @@ -46,6 +46,12 @@ public class LocalHistoryFacade { myChangeList.beginChangeSet(); } + public void forceBeginChangeSet() { + if (myChangeList.forceBeginChangeSet()) { + fireChangeSetFinished(); + } + } + public void endChangeSet(String name) { if (myChangeList.endChangeSet(name)) { fireChangeSetFinished(); diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.java b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.java index 382007d81a0a..3d345e1614d6 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.java @@ -30,9 +30,7 @@ public class LocalHistoryEventDispatcher extends VirtualFileAdapter implements V private static final Key WAS_VERSIONED_KEY = Key.create(LocalHistoryEventDispatcher.class.getSimpleName() + ".WAS_VERSIONED_KEY"); private final LocalHistoryFacade myVcs; - private final IdeaGateway myGateway; - private int myChangeSetDepth = 0; public LocalHistoryEventDispatcher(LocalHistoryFacade vcs, IdeaGateway gw) { myVcs = vcs; @@ -64,41 +62,22 @@ public class LocalHistoryEventDispatcher extends VirtualFileAdapter implements V public void undoTransparentActionFinished() { } - public synchronized void startAction() { - // save document in current or new changeset and close it - if (myChangeSetDepth == 0) { - myVcs.beginChangeSet(); - } + public void startAction() { myGateway.registerUnsavedDocuments(myVcs); - myVcs.endChangeSet(null); - - // restore changeset if there were before saving the documents - if (myChangeSetDepth > 0) { - myVcs.beginChangeSet(); - } - - beginChangeSet(); + myVcs.forceBeginChangeSet(); } - public synchronized void finishAction(String name) { + public void finishAction(String name) { myGateway.registerUnsavedDocuments(myVcs); endChangeSet(name); } - private synchronized void beginChangeSet() { - myChangeSetDepth++; - if (myChangeSetDepth == 1) { - myVcs.beginChangeSet(); - } + private void beginChangeSet() { + myVcs.beginChangeSet(); } - private synchronized void endChangeSet(String name) { - LocalHistoryLog.LOG.assertTrue(myChangeSetDepth > 0, "changeset depth is invalid"); - - myChangeSetDepth--; - if (myChangeSetDepth == 0) { - myVcs.endChangeSet(name); - } + private void endChangeSet(String name) { + myVcs.endChangeSet(name); } @Override @@ -113,7 +92,7 @@ public class LocalHistoryEventDispatcher extends VirtualFileAdapter implements V myVcs.created(f.getPath(), f.isDirectory()); } if (f.isDirectory()) { - for (VirtualFile each : ((NewVirtualFile)f).getChildren()) { + for (VirtualFile each : ((NewVirtualFile)f).iterInDbChildren()) { createRecursively(each); } } diff --git a/platform/lvcs-impl/testSrc/com/intellij/history/core/changes/ChangeListTest.java b/platform/lvcs-impl/testSrc/com/intellij/history/core/changes/ChangeListTest.java index bbad3b6760ff..d59e4561157e 100644 --- a/platform/lvcs-impl/testSrc/com/intellij/history/core/changes/ChangeListTest.java +++ b/platform/lvcs-impl/testSrc/com/intellij/history/core/changes/ChangeListTest.java @@ -115,6 +115,28 @@ public class ChangeListTest extends ChangeListTestCase { assertEquals(array(c1, c2), cc.get(0).getChanges()); } + @Test + public void testForcesBegin() throws Exception { + facade.beginChangeSet(); + add(facade, createFile(r, "f1")); + facade.beginChangeSet(); + add(facade, createFile(r, "f2")); + facade.forceBeginChangeSet(); + add(facade, createFile(r, "f3")); + facade.endChangeSet("a"); + add(facade, createFile(r, "f4")); + facade.endChangeSet("b"); + add(facade, createFile(r, "f5")); + facade.endChangeSet("c"); + + List cc = facade.getChangeListInTests().getChangesInTests(); + assertEquals(2, cc.size()); + assertEquals("c", cc.get(0).getName()); + assertEquals(3, cc.get(0).getChanges().size()); + assertEquals(null, cc.get(1).getName()); + assertEquals(2, cc.get(1).getChanges().size()); + } + @Test public void testChangeSetTimestamp() { setCurrentTimestamp(123);