From f28be8d6e71f78ff614ed18048bd96d22ab00f10 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 19 May 2010 21:19:34 +0400 Subject: [PATCH 01/23] don't run HgExecutableValidator in unit test mode --- plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java index 22f056150310..ebd2f4e693b6 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java @@ -192,8 +192,13 @@ public class HgVcs extends AbstractVcs { protected void start() throws VcsException { ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { - HgExecutableValidator validator = new HgExecutableValidator(myProject); - started = validator.check(globalSettings); + if (ApplicationManager.getApplication().isUnitTestMode()) { + started = true; + } + else { + HgExecutableValidator validator = new HgExecutableValidator(myProject); + started = validator.check(globalSettings); + } if (isStarted()) { addListeners(); } From 12c0c9d742c0fc6dde2d0789652975740ebab559 Mon Sep 17 00:00:00 2001 From: Roman Chernyatchik Date: Wed, 19 May 2010 22:09:41 +0400 Subject: [PATCH 02/23] Test Runner API and Semantics updated. See http://jetbrains-feed.appspot.com/message/261002 --- .../sm/SMTestRunnerConnectionUtil.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/SMTestRunnerConnectionUtil.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/SMTestRunnerConnectionUtil.java index dc71ad9d28cc..6a7f3ee1e1e2 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/SMTestRunnerConnectionUtil.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/SMTestRunnerConnectionUtil.java @@ -60,19 +60,20 @@ public class SMTestRunnerConnectionUtil { * consistency of test events communication protocol and throw assertion errors. To enable debug mode * please set system property idea.smrunner.debug=true * - * @param processHandler Process handler - * @param consoleProperties Console properties for test console actions * @param testFrameworkName Is used to store(project level) latest value of testTree/consoleTab splitter and other settings * and also will be mentioned in debug diagnostics + * @param processHandler Process handler + * @param consoleProperties Console properties for test console actions * @return Console view * @throws ExecutionException If IDEA cannot execute process this Exception will * be caught and shown in error message box */ - public static BaseTestsOutputConsoleView attachRunner(@NotNull final ProcessHandler processHandler, + public static BaseTestsOutputConsoleView attachRunner(@NotNull final String testFrameworkName, + @NotNull final ProcessHandler processHandler, @NotNull final TestConsoleProperties consoleProperties, final RunnerSettings runnerSettings, - final ConfigurationPerRunnerSettings configurationSettings, - @NotNull final String testFrameworkName) throws ExecutionException { + final ConfigurationPerRunnerSettings configurationSettings + ) throws ExecutionException { // Console final String splitterPropertyName = testFrameworkName + ".Splitter.Proportion"; @@ -126,24 +127,24 @@ public class SMTestRunnerConnectionUtil { * consistency of test events communication protocol and throw assertion errors. To enable debug mode * please set system property idea.smrunner.debug=true * + * @param testFrameworkName Is used to store(project level) latest value of testTree/consoleTab splitter and other settings * @param processHandler Process handler * @param commandLineState Command line state * @param config User run configuration settings - * @param testFrameworkName Is used to store(project level) latest value of testTree/consoleTab splitter and other settings * @return Console view * @throws ExecutionException If IDEA cannot execute process this Exception will * be caught and shown in error message box */ - public static ConsoleView attachRunner(@NotNull final ProcessHandler processHandler, + public static ConsoleView attachRunner(@NotNull final String testFrameworkName, @NotNull final ProcessHandler processHandler, @NotNull final CommandLineState commandLineState, - @NotNull final RuntimeConfiguration config, - @NotNull final String testFrameworkName) throws ExecutionException { + @NotNull final RuntimeConfiguration config + ) throws ExecutionException { // final String testFrameworkName final TestConsoleProperties consoleProperties = new SMTRunnerConsoleProperties(config, testFrameworkName); - return attachRunner(processHandler, consoleProperties, + return attachRunner(testFrameworkName, processHandler, consoleProperties, commandLineState.getRunnerSettings(), - commandLineState.getConfigurationSettings(), testFrameworkName); + commandLineState.getConfigurationSettings()); } /** From 1fcac16907b2d465f1e7f68ecd436396f91106b5 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 10:58:05 +0400 Subject: [PATCH 03/23] IDEA-55132 Provide ability to setup formatter to use indents relative to expression start 1. Added 'use indents relative to expression start' processing; 2. Added javadoc; 3. Minor local refactorings; --- .../formatting/AbstractBlockWrapper.java | 75 ++++++++++++------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java index 6b3bddec876c..56c7ccc48aa4 100644 --- a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java +++ b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java @@ -21,11 +21,24 @@ import com.intellij.psi.codeStyle.CodeStyleSettings; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import static java.util.Arrays.asList; /** * @author lesya */ public abstract class AbstractBlockWrapper { + + private static final Set RELATIVE_INDENT_TYPES = new HashSet(asList( + IndentImpl.Type.NORMAL, IndentImpl.Type.CONTINUATION, IndentImpl.Type.CONTINUATION_WITHOUT_FIRST + )); + + private static final Set CONTINUATION_INDENT_TYPES = new HashSet(asList( + IndentImpl.Type.CONTINUATION, IndentImpl.Type.CONTINUATION_WITHOUT_FIRST + )); + protected WhiteSpace myWhiteSpace; protected CompositeBlockWrapper myParent; protected int myStart; @@ -154,36 +167,38 @@ public abstract class AbstractBlockWrapper { } - public IndentData getChildOffset(AbstractBlockWrapper child, CodeStyleSettings.IndentOptions options, final int tokenBlockStartOffset) { + public IndentData getChildOffset(AbstractBlockWrapper child, CodeStyleSettings.IndentOptions options, int targetBlockStartOffset) { final boolean childOnNewLine = child.getWhiteSpace().containsLineFeeds(); + IndentImpl.Type childIndentType = child.getIndent().getType(); final IndentData childIndent; // Calculate child indent. - if (childOnNewLine) { - childIndent = getIndent(options, child, tokenBlockStartOffset); + if (childOnNewLine + || (!getWhiteSpace().containsLineFeeds() && RELATIVE_INDENT_TYPES.contains(childIndentType) && indentAlreadyUsedBefore(child))) + { + childIndent = getIndent(options, child, targetBlockStartOffset); } else { - IndentImpl.Type type = child.getIndent().getType(); - if (!getWhiteSpace().containsLineFeeds() - && (type == IndentImpl.Type.NORMAL || type == IndentImpl.Type.CONTINUATION || type == IndentImpl.Type.CONTINUATION_WITHOUT_FIRST) - && indentAlreadyUsedBefore(child)) - { - childIndent = getIndent(options, child, tokenBlockStartOffset); - } - else { - childIndent = new IndentData(0); - } + childIndent = new IndentData(0); } + // Use child indent if it's absolute and the child is contained on new line. - if (childOnNewLine && child.getIndent().isAbsolute()) { - myFlags &= ~CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT; - AbstractBlockWrapper current = this; - while (current != null && current.getStartOffset() == getStartOffset()) { - current.myFlags &= ~CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT; - current = current.myParent; + if (childOnNewLine) { + if (child.getIndent().isAbsolute()) { + myFlags &= ~CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT; + AbstractBlockWrapper current = this; + while (current != null && current.getStartOffset() == getStartOffset()) { + current.myFlags &= ~CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT; + current = current.myParent; + } + return childIndent; + } + else if (options.USE_RELATIVE_INDENTS && child.getStartOffset() > getStartOffset() + && (CONTINUATION_INDENT_TYPES.contains(childIndentType))) + { + return childIndent.add(getNumberOfSymbolsBeforeBlock()); } - return childIndent; } if (child.getStartOffset() == getStartOffset()) { @@ -192,25 +207,25 @@ public abstract class AbstractBlockWrapper { setCanUseFirstChildIndentAsBlockIndent(newValue); } - if (getStartOffset() == tokenBlockStartOffset) { + if (getStartOffset() == targetBlockStartOffset) { if (myParent == null) { return childIndent; } else { - return childIndent.add(myParent.getChildOffset(this, options, tokenBlockStartOffset)); + return childIndent.add(myParent.getChildOffset(this, options, targetBlockStartOffset)); } } else if (!getWhiteSpace().containsLineFeeds()) { if (isIndentAffectedAlignment(child)) { return createAlignmentIndent(childIndent, child); } else { - return childIndent.add(myParent.getChildOffset(this, options, tokenBlockStartOffset)); + return childIndent.add(myParent.getChildOffset(this, options, targetBlockStartOffset)); } } else { if (myParent == null) return childIndent.add(getWhiteSpace()); if (getIndent().isAbsolute()) { if (myParent.myParent != null) { - return childIndent.add(myParent.myParent.getChildOffset(myParent, options, tokenBlockStartOffset)); + return childIndent.add(myParent.myParent.getChildOffset(myParent, options, targetBlockStartOffset)); } else { return childIndent.add(getWhiteSpace()); @@ -225,7 +240,7 @@ public abstract class AbstractBlockWrapper { } } else { - return childIndent.add(myParent.getChildOffset(this, options, tokenBlockStartOffset)); + return childIndent.add(myParent.getChildOffset(this, options, targetBlockStartOffset)); } } } @@ -252,7 +267,7 @@ public abstract class AbstractBlockWrapper { * @return previous block for the current block if any; null otherwise */ @Nullable - protected abstract AbstractBlockWrapper getPreviousBlock(); + protected abstract LeafBlockWrapper getPreviousBlock(); protected final void setCanUseFirstChildIndentAsBlockIndent(final boolean newValue) { if (newValue) myFlags |= CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT; @@ -287,10 +302,12 @@ public abstract class AbstractBlockWrapper { } /** - * Allows to answer if indent for the given child block should be calculated + * Allows to answer if indent for the given child block should be calculated taking into consideration alignment + * of the text at current block start. * - * @param child - * @return + * @param child child block to check + * @return true if indent should be calculated taking into consideration alignment of the text at current + * block start; false otherwise */ private boolean isIndentAffectedAlignment(AbstractBlockWrapper child) { if (!child.getWhiteSpace().containsLineFeeds()) { From 6ba5ba6e11d8186f9a4abef388e02d46c114480b Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 10:58:42 +0400 Subject: [PATCH 04/23] Added method for convenient access to indentation options from formatter tests --- .../psi/formatter/java/AbstractJavaFormatterTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/AbstractJavaFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/AbstractJavaFormatterTest.java index 5856580ab5f6..39769d391749 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/AbstractJavaFormatterTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/AbstractJavaFormatterTest.java @@ -22,6 +22,7 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.impl.DocumentImpl; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -74,6 +75,10 @@ public abstract class AbstractJavaFormatterTest extends LightIdeaTestCase { return CodeStyleSettingsManager.getSettings(getProject()); } + public static CodeStyleSettings.IndentOptions getIndentOptions() { + return getSettings().getIndentOptions(StdFileTypes.JAVA); + } + public void doTest() throws Exception { doTest(getTestName(false) + ".java", getTestName(false) + "_after.java"); } From cba657be42bc0c2fb2804158a6dbfd47df48b904 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 10:59:07 +0400 Subject: [PATCH 05/23] IDEA-55132 Provide ability to setup formatter to use indents relative to expression start Added 'use indents relative to expression start' label text --- .../src/messages/ApplicationBundle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index 35484a910385..e2ff7ecda4a9 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -340,6 +340,7 @@ editbox.indent.continuation.indent=Continuation indent editbox.indent.label.indent=Label indent checkbox.indent.absolute.label.indent=Absolute label indent checkbox.do.not.indent.top.level.class.members=Do not indent top level class members +checkbox.use.relative.indents=Use indents relative to expression start tooltip.indent.must.be.multiple.of.tab.size.for.smart.tabs.to.operate=Indent must be multiple of tab size for smart tabs to operate combobox.crlf.system.dependent=System Dependent combobox.crlf.unix=Unix \n From 29400956fd51b670e5ff252a7bfdba8ca4b5e506 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 10:59:44 +0400 Subject: [PATCH 06/23] IDEA-55132 Provide ability to setup formatter to use indents relative to expression start Added 'use indents relative to expression start' option --- .../src/com/intellij/psi/codeStyle/CodeStyleSettings.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java index 804170323dfa..95116298fa59 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java @@ -199,6 +199,7 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { public boolean SMART_TABS = false; public int LABEL_INDENT_SIZE = 0; public boolean LABEL_INDENT_ABSOLUTE = false; + public boolean USE_RELATIVE_INDENTS = false; public void readExternal(Element element) throws InvalidDataException { DefaultJDOMExternalizer.readExternal(this, element); @@ -228,6 +229,7 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { if (CONTINUATION_INDENT_SIZE != that.CONTINUATION_INDENT_SIZE) return false; if (INDENT_SIZE != that.INDENT_SIZE) return false; if (LABEL_INDENT_ABSOLUTE != that.LABEL_INDENT_ABSOLUTE) return false; + if (USE_RELATIVE_INDENTS != that.USE_RELATIVE_INDENTS) return false; if (LABEL_INDENT_SIZE != that.LABEL_INDENT_SIZE) return false; if (SMART_TABS != that.SMART_TABS) return false; if (TAB_SIZE != that.TAB_SIZE) return false; @@ -245,6 +247,7 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { result = 31 * result + (SMART_TABS ? 1 : 0); result = 31 * result + LABEL_INDENT_SIZE; result = 31 * result + (LABEL_INDENT_ABSOLUTE ? 1 : 0); + result = 31 * result + (USE_RELATIVE_INDENTS ? 1 : 0); return result; } From 98135922a46b9969fb005119468a301452661025 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 11:00:23 +0400 Subject: [PATCH 07/23] IDEA-55132 Provide ability to setup formatter to use indents relative to expression start Adopted to changed 'getPreviousBlock()' return type --- .../src/com/intellij/formatting/CompositeBlockWrapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/CompositeBlockWrapper.java b/platform/lang-impl/src/com/intellij/formatting/CompositeBlockWrapper.java index 805bbf49aff0..dca827b624f4 100644 --- a/platform/lang-impl/src/com/intellij/formatting/CompositeBlockWrapper.java +++ b/platform/lang-impl/src/com/intellij/formatting/CompositeBlockWrapper.java @@ -75,7 +75,7 @@ public class CompositeBlockWrapper extends AbstractBlockWrapper{ } @Override - protected AbstractBlockWrapper getPreviousBlock() { + protected LeafBlockWrapper getPreviousBlock() { if (myChildren == null || myChildren.isEmpty()) { return null; } From 959ff1fd1e0c59b428ab6a80e5aadb640c44275c Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 11:01:09 +0400 Subject: [PATCH 08/23] 1. Code formatting is corrected; 2. Unnecessary method is removed; --- .../src/com/intellij/formatting/LeafBlockWrapper.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/LeafBlockWrapper.java b/platform/lang-impl/src/com/intellij/formatting/LeafBlockWrapper.java index 4bd3df4d8489..99b38484192a 100644 --- a/platform/lang-impl/src/com/intellij/formatting/LeafBlockWrapper.java +++ b/platform/lang-impl/src/com/intellij/formatting/LeafBlockWrapper.java @@ -151,8 +151,6 @@ class LeafBlockWrapper extends AbstractBlockWrapper { return new IndentData(indentSpaces, spaces); } - - public void dispose() { super.dispose(); myPreviousBlock = null; @@ -230,9 +228,4 @@ class LeafBlockWrapper extends AbstractBlockWrapper { public TextRange getTextRange() { return new TextRange(myStart, myEnd); } - - private void calculateNumberOfSymbolsAtLastLine() { - - } - } From 93f58eb29d73d860c229c157644a7a28f607c1b2 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 11:01:40 +0400 Subject: [PATCH 09/23] IDEA-55132 Provide ability to setup formatter to use indents relative to expression start Corresponding test is added --- .../java/JavaFormatterIndentationTest.java | 127 ++++++++++++++---- 1 file changed, 98 insertions(+), 29 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java index 6280a7e91a12..511450a9f617 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java @@ -173,34 +173,103 @@ public class JavaFormatterIndentationTest extends AbstractJavaFormatterTest { public void testCaseFromSwitch() throws IncorrectOperationException { // Inspired by IDEADEV-22920 getSettings().INDENT_CASE_FROM_SWITCH = false; - doTextTest("class Foo{\n" + - "void foo () {\n" + - "switch(someValue) {\n" + - " // This comment is correctly not-indented\n" + - " case 1:\n" + - " doSomething();\n" + - " break;\n" + - "\n" + - " // This comment should not be indented, but it is\n" + - " case 2:\n" + - " doSomethingElse();\n" + - " break;\n" + - "}\n" + - "}\n" + - "}", "class Foo {\n" + - " void foo() {\n" + - " switch (someValue) {\n" + - " // This comment is correctly not-indented\n" + - " case 1:\n" + - " doSomething();\n" + - " break;\n" + - "\n" + - " // This comment should not be indented, but it is\n" + - " case 2:\n" + - " doSomethingElse();\n" + - " break;\n" + - " }\n" + - " }\n" + - "}"); + doTextTest( + "class Foo{\n" + + "void foo () {\n" + + "switch(someValue) {\n" + + " // This comment is correctly not-indented\n" + + " case 1:\n" + + " doSomething();\n" + + " break;\n" + + "\n" + + " // This comment should not be indented, but it is\n" + + " case 2:\n" + + " doSomethingElse();\n" + + " break;\n" + + "}\n" + + "}\n" + + "}", + + "class Foo {\n" + + " void foo() {\n" + + " switch (someValue) {\n" + + " // This comment is correctly not-indented\n" + + " case 1:\n" + + " doSomething();\n" + + " break;\n" + + "\n" + + " // This comment should not be indented, but it is\n" + + " case 2:\n" + + " doSomethingElse();\n" + + " break;\n" + + " }\n" + + " }\n" + + "}"); + } + + public void testBinaryExpressionsWithRelativeIndents() { + // Inspired by IDEA-21795 + getIndentOptions().USE_RELATIVE_INDENTS = true; + getIndentOptions().CONTINUATION_INDENT_SIZE = 4; + + doTextTest( + "public class FormattingTest {\n" + + "\n" + + " public boolean test1(int a, int b, int c, int d) {\n" + + " return a == 1 &&\n" + + " b == 2;\n" + + " }\n" + + "\n" + + " public boolean multilineSignOnCurrent(int a, int b, int c, int d) {\n" + + " return a == 0 &&\n" + + " (b == 0 ||\n" + + " c == 0) &&\n" + + " d == 0;\n" + + " }\n" + + "\n" + + " public boolean multilineSignOnNext(int a, int b, int c, int d) {\n" + + " return a == 0\n" + + " && (b == 0\n" + + " || c == 0)\n" + + " && d == 0;\n" + + " }\n" + + "\n" + + " public boolean expectedMultilineSignOnNext(int a, int b, int c, int d) {\n" + + " return a == 0\n" + + " && (b == 0\n" + + " || c == 0)\n" + + " && d == 0;\n" + + " }\n" + + "}", + + "public class FormattingTest {\n" + + "\n" + + " public boolean test1(int a, int b, int c, int d) {\n" + + " return a == 1 &&\n" + + " b == 2;\n" + + " }\n" + + "\n" + + " public boolean multilineSignOnCurrent(int a, int b, int c, int d) {\n" + + " return a == 0 &&\n" + + " (b == 0 ||\n" + + " c == 0) &&\n" + + " d == 0;\n" + + " }\n" + + "\n" + + " public boolean multilineSignOnNext(int a, int b, int c, int d) {\n" + + " return a == 0\n" + + " && (b == 0\n" + + " || c == 0)\n" + + " && d == 0;\n" + + " }\n" + + "\n" + + " public boolean expectedMultilineSignOnNext(int a, int b, int c, int d) {\n" + + " return a == 0\n" + + " && (b == 0\n" + + " || c == 0)\n" + + " && d == 0;\n" + + " }\n" + + "}" + ); } } From 720c1a198d9db4aae4440f725b716c52221a4516 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 11:02:05 +0400 Subject: [PATCH 10/23] IDEA-55132 Provide ability to setup formatter to use indents relative to expression start Added GUI element for controlling 'use indents relative to expression start' option --- .../application/options/JavaIndentOptionsEditor.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/java/java-impl/src/com/intellij/application/options/JavaIndentOptionsEditor.java b/java/java-impl/src/com/intellij/application/options/JavaIndentOptionsEditor.java index 54a551efe67d..19ae70407ef6 100644 --- a/java/java-impl/src/com/intellij/application/options/JavaIndentOptionsEditor.java +++ b/java/java-impl/src/com/intellij/application/options/JavaIndentOptionsEditor.java @@ -30,6 +30,7 @@ public class JavaIndentOptionsEditor extends SmartIndentOptionsEditor { private JCheckBox myLabelIndentAbsolute; private JCheckBox myCbDontIndentTopLevelMembers; + private JCheckBox myCbUseRelativeIndent; protected void addComponents() { super.addComponents(); @@ -42,6 +43,9 @@ public class JavaIndentOptionsEditor extends SmartIndentOptionsEditor { myCbDontIndentTopLevelMembers = new JCheckBox(ApplicationBundle.message("checkbox.do.not.indent.top.level.class.members")); add(myCbDontIndentTopLevelMembers); + + myCbUseRelativeIndent = new JCheckBox(ApplicationBundle.message("checkbox.use.relative.indents")); + add(myCbUseRelativeIndent); } public boolean isModified(final CodeStyleSettings settings, final CodeStyleSettings.IndentOptions options) { @@ -50,6 +54,7 @@ public class JavaIndentOptionsEditor extends SmartIndentOptionsEditor { isModified |= isFieldModified(myLabelIndent, options.LABEL_INDENT_SIZE); isModified |= isFieldModified(myLabelIndentAbsolute, options.LABEL_INDENT_ABSOLUTE); isModified |= isFieldModified(myCbDontIndentTopLevelMembers, settings.DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS); + isModified |= isFieldModified(myCbUseRelativeIndent, options.USE_RELATIVE_INDENTS); return isModified; } @@ -64,6 +69,7 @@ public class JavaIndentOptionsEditor extends SmartIndentOptionsEditor { } options.LABEL_INDENT_ABSOLUTE = myLabelIndentAbsolute.isSelected(); settings.DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS = myCbDontIndentTopLevelMembers.isSelected(); + options.USE_RELATIVE_INDENTS = myCbUseRelativeIndent.isSelected(); } public void reset(@NotNull final CodeStyleSettings settings, @NotNull final CodeStyleSettings.IndentOptions options) { @@ -71,6 +77,7 @@ public class JavaIndentOptionsEditor extends SmartIndentOptionsEditor { myLabelIndent.setText(Integer.toString(options.LABEL_INDENT_SIZE)); myLabelIndentAbsolute.setSelected(options.LABEL_INDENT_ABSOLUTE); myCbDontIndentTopLevelMembers.setSelected(settings.DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS); + myCbUseRelativeIndent.setSelected(options.USE_RELATIVE_INDENTS); } public void setEnabled(final boolean enabled) { From 3aa1bfd899045f9baff1562e0a865ee75e171742 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 20 May 2010 12:14:31 +0400 Subject: [PATCH 11/23] don't execute postponed tasks if already disposed --- .../hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java | 3 ++- .../hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java | 3 ++- plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java index b52cf875ee56..63d5ef6cfae0 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java @@ -46,6 +46,7 @@ class HgIncomingStatusUpdater implements HgUpdater { public void run() { new Task.Backgroundable(project, "Checking Incoming Changesets", true) { public void run(@NotNull ProgressIndicator indicator) { + if (project.isDisposed()) return; HgIncomingCommand command = new HgIncomingCommand(project); VcsRoot[] roots = ProjectLevelVcsManager.getInstance(project).getAllVcsRoots(); List changesets = new LinkedList(); @@ -57,7 +58,7 @@ class HgIncomingStatusUpdater implements HgUpdater { } }.queue(); } - }); + }, project.getDisposed()); } private final class IncomingChangesetFormatter implements HgChangesetStatus.ChangesetWriter { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java index 0cb3d58e7785..6cf9d12d8e6b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java @@ -46,6 +46,7 @@ class HgOutgoingStatusUpdater implements HgUpdater { public void run() { new Task.Backgroundable(project, "Checking Outgoing Changesets", true) { public void run(@NotNull ProgressIndicator indicator) { + if (project.isDisposed()) return; HgOutgoingCommand command = new HgOutgoingCommand(project); VcsRoot[] roots = ProjectLevelVcsManager.getInstance(project).getAllVcsRoots(); List outgoing = new LinkedList(); @@ -57,7 +58,7 @@ class HgOutgoingStatusUpdater implements HgUpdater { } }.queue(); } - }); + }, project.getDisposed()); } private final class OutgoingChangesetFormatter implements HgChangesetStatus.ChangesetWriter { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java index ebd2f4e693b6..c8994cff9c0b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java @@ -203,7 +203,7 @@ public class HgVcs extends AbstractVcs { addListeners(); } } - }); + }, myProject.getDisposed()); } @Override From 1f2217bf6a229f7f9c77c5da1af3d5685ee6169e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 20 May 2010 12:41:16 +0400 Subject: [PATCH 12/23] I see dead code (TM) --- .../codeStyle/OptionTreeWithPreviewPanel.java | 178 ++---------------- 1 file changed, 20 insertions(+), 158 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTreeWithPreviewPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTreeWithPreviewPanel.java index d1a884083fc8..46ed4d5f7801 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTreeWithPreviewPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTreeWithPreviewPanel.java @@ -15,27 +15,14 @@ */ package com.intellij.application.options.codeStyle; -import com.intellij.application.options.CodeStyleAbstractPanel; -import com.intellij.ide.DataManager; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.colors.EditorColorsScheme; -import com.intellij.openapi.editor.highlighter.EditorHighlighter; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.fileTypes.LanguageFileType; -import com.intellij.openapi.fileTypes.StdFileTypes; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.containers.HashMap; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.tree.*; @@ -46,7 +33,6 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.Arrays; /** * @author max @@ -54,8 +40,8 @@ import java.util.Arrays; public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleAbstractPanel { private static final Logger LOG = Logger.getInstance("#com.intellij.application.options.CodeStyleSpacesPanel"); private final JTree myOptionsTree; - private final HashMap myKeyToFieldMap = new HashMap(); - private final ArrayList myKeys = new ArrayList(); + private final HashMap myKeyToFieldMap = new HashMap(); + private final ArrayList myKeys = new ArrayList(); private final JPanel myPanel = new JPanel(new GridBagLayout()); public OptionTreeWithPreviewPanel(CodeStyleSettings settings) { @@ -84,32 +70,14 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(); String groupName = ""; DefaultMutableTreeNode groupNode = null; - for (int i = 0; i < myKeys.size(); i++) { - if (myKeys.get(i) instanceof BooleanOptionKey) { - BooleanOptionKey key = (BooleanOptionKey)myKeys.get(i); - String newGroupName = key.groupName; - if (!newGroupName.equals(groupName) || groupNode == null) { - groupName = newGroupName; - groupNode = new DefaultMutableTreeNode(newGroupName); - rootNode.add(groupNode); - } - groupNode.add(new MyToggleTreeNode(key, key.cbName)); - } - else if (myKeys.get(i) instanceof IntSelectionOptionKey) { - IntSelectionOptionKey key = (IntSelectionOptionKey)myKeys.get(i); - String newGroupName = key.groupName; - if (!newGroupName.equals(groupName) || groupNode == null) { - groupName = newGroupName; - groupNode = new DefaultMutableTreeNode(newGroupName); - rootNode.add(groupNode); - } - MyToggleTreeNode[] nodes = new MyToggleTreeNode[key.rbNames.length]; - for (int j = 0; j < nodes.length; j++) { - nodes[j] = new MyToggleTreeNode(key, key.rbNames[j]); - groupNode.add(nodes[j]); - } - key.setCreatedNodes(nodes); + for (BooleanOptionKey key: myKeys) { + String newGroupName = key.groupName; + if (!newGroupName.equals(groupName) || groupNode == null) { + groupName = newGroupName; + groupNode = new DefaultMutableTreeNode(newGroupName); + rootNode.add(groupNode); } + groupNode.add(new MyToggleTreeNode(key, key.cbName)); } DefaultTreeModel model = new DefaultTreeModel(rootNode); @@ -156,19 +124,7 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA Object o = treePath.getLastPathComponent(); if (o instanceof MyToggleTreeNode) { MyToggleTreeNode node = (MyToggleTreeNode)o; - if (node.isCheckbox()) { - node.setSelected(!node.isSelected()); - } - else { - MyToggleTreeNode[] group = node.getGroup(); - for (int i = 0; i < group.length; i++) { - MyToggleTreeNode groupNode = group[i]; - groupNode.setSelected(false); - int row = myOptionsTree.getRowForPath(new TreePath(groupNode.getPath())); - myOptionsTree.repaint(myOptionsTree.getRowBounds(row)); - } - node.setSelected(true); - } + node.setSelected(!node.isSelected()); int row = myOptionsTree.getRowForPath(treePath); myOptionsTree.repaint(myOptionsTree.getRowBounds(row)); //updatePreview(); @@ -201,21 +157,9 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA private void resetMyTreeNode(MyToggleTreeNode childNode, final CodeStyleSettings settings) { try { - if (childNode.getKey() instanceof BooleanOptionKey) { - BooleanOptionKey key = (BooleanOptionKey)childNode.getKey(); - Field field = (Field)myKeyToFieldMap.get(key); - childNode.setSelected(field.getBoolean(settings)); - } - else if (childNode.getKey() instanceof IntSelectionOptionKey) { - IntSelectionOptionKey key = (IntSelectionOptionKey)childNode.getKey(); - Field field = (Field)myKeyToFieldMap.get(key); - int fieldValue = field.getInt(settings); - for (int i = 0; i < key.rbNames.length; i++) { - if (childNode.getText().equals(key.rbNames[i])) { - childNode.setSelected(fieldValue == key.values[i]); - } - } - } + BooleanOptionKey key = (BooleanOptionKey)childNode.getKey(); + Field field = myKeyToFieldMap.get(key); + childNode.setSelected(field.getBoolean(settings)); } catch (IllegalArgumentException e) { LOG.error(e); @@ -244,22 +188,9 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA private void applyToggleNode(MyToggleTreeNode childNode, final CodeStyleSettings settings) { try { - if (childNode.getKey() instanceof BooleanOptionKey) { - BooleanOptionKey key = (BooleanOptionKey)childNode.getKey(); - Field field = (Field)myKeyToFieldMap.get(key); - field.set(settings, childNode.isSelected() ? Boolean.TRUE : Boolean.FALSE); - } - else if (childNode.getKey() instanceof IntSelectionOptionKey) { - if (!childNode.isSelected()) return; - IntSelectionOptionKey key = (IntSelectionOptionKey)childNode.getKey(); - Field field = (Field)myKeyToFieldMap.get(key); - for (int i = 0; i < key.rbNames.length; i++) { - if (childNode.getText().equals(key.rbNames[i])) { - field.set(settings, new Integer(key.values[i])); - break; - } - } - } + BooleanOptionKey key = (BooleanOptionKey)childNode.getKey(); + Field field = myKeyToFieldMap.get(key); + field.set(settings, childNode.isSelected() ? Boolean.TRUE : Boolean.FALSE); } catch (IllegalArgumentException e) { LOG.error(e); @@ -296,21 +227,9 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA private boolean isToggleNodeModified(MyToggleTreeNode childNode, final CodeStyleSettings settings) { try { - if (childNode.getKey() instanceof BooleanOptionKey) { - BooleanOptionKey key = (BooleanOptionKey)childNode.getKey(); - Field field = (Field)myKeyToFieldMap.get(key); - return childNode.isSelected() != field.getBoolean(settings); - } - else if (childNode.getKey() instanceof IntSelectionOptionKey) { - if (!childNode.isSelected()) return false; - IntSelectionOptionKey key = (IntSelectionOptionKey)childNode.getKey(); - Field field = (Field)myKeyToFieldMap.get(key); - for (int i = 0; i < key.rbNames.length; i++) { - if (childNode.getText().equals(key.rbNames[i])) { - return field.getInt(settings) != key.values[i]; - } - } - } + BooleanOptionKey key = (BooleanOptionKey)childNode.getKey(); + Field field = myKeyToFieldMap.get(key); + return childNode.isSelected() != field.getBoolean(settings); } catch (IllegalArgumentException e) { LOG.error(e); @@ -335,20 +254,6 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA } } - protected void initRadioGroupField(String fieldName, String groupName, String[] rbNames, int[] values) { - try { - Class styleSettingsClass = CodeStyleSettings.class; - Field field = styleSettingsClass.getField(fieldName); - IntSelectionOptionKey key = new IntSelectionOptionKey(groupName, rbNames, values); - myKeyToFieldMap.put(key, field); - myKeys.add(key); - } - catch (NoSuchFieldException e) { - } - catch (SecurityException e) { - } - } - protected void prepareForReformat(final PsiFile psiFile) { //psiFile.putUserData(PsiUtil.FILE_LANGUAGE_LEVEL_KEY, LanguageLevel.HIGHEST); } @@ -356,12 +261,10 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA protected class MyTreeCellRenderer implements TreeCellRenderer { private final MyLabelPanel myLabel; private final JCheckBox myCheckBox; - private final JRadioButton myRadioButton; public MyTreeCellRenderer() { myLabel = new MyLabelPanel(); myCheckBox = new JCheckBox(); - myRadioButton = new JRadioButton(); myCheckBox.setMargin(new Insets(0, 0, 0, 0)); } @@ -370,7 +273,7 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA if (value instanceof MyToggleTreeNode) { MyToggleTreeNode treeNode = (MyToggleTreeNode)value; - JToggleButton button = treeNode.isCheckbox() ? (JToggleButton)myCheckBox : (JToggleButton)myRadioButton; + JToggleButton button = myCheckBox; button.setText(treeNode.getText()); button.setSelected(treeNode.isSelected); if (isSelected) { @@ -473,64 +376,23 @@ public abstract class OptionTreeWithPreviewPanel extends MultilanguageCodeStyleA } } - private static class IntSelectionOptionKey { - final String groupName; - final String[] rbNames; - final int[] values; - private MyToggleTreeNode[] myNodes; - - public IntSelectionOptionKey(String groupName, String[] rbNames, int[] values) { - this.groupName = groupName; - this.rbNames = rbNames; - this.values = values; - } - - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof IntSelectionOptionKey)) return false; - - final IntSelectionOptionKey intSelectionOptionKey = (IntSelectionOptionKey)o; - - if (!groupName.equals(intSelectionOptionKey.groupName)) return false; - if (!Arrays.equals(rbNames, intSelectionOptionKey.rbNames)) return false; - - return true; - } - - public int hashCode() { - return groupName.hashCode() + rbNames[0].hashCode() * 29; - } - - public void setCreatedNodes(MyToggleTreeNode[] nodes) { myNodes = nodes; } - - public MyToggleTreeNode[] getNodes() { return myNodes; } - } - private static class MyToggleTreeNode extends DefaultMutableTreeNode { private final Object myKey; private final String myText; private boolean isSelected; - private final boolean isCheckbox; public MyToggleTreeNode(Object key, String text) { myKey = key; myText = text; - isCheckbox = true; } public Object getKey() { return myKey; } public String getText() { return myText; } - public boolean isCheckbox() { return isCheckbox; } - public void setSelected(boolean val) { isSelected = val; } public boolean isSelected() { return isSelected; } - - public MyToggleTreeNode[] getGroup() { - return ((IntSelectionOptionKey)myKey).getNodes(); - } } public JComponent getInternalPanel() { From 193fde64cdb9525cbb16dd3591bb085243f6d83d Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 20 May 2010 13:03:55 +0400 Subject: [PATCH 13/23] Mercurial init logic moved from start() to activate() --- plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java index c8994cff9c0b..01152182d8b1 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java @@ -189,7 +189,7 @@ public class HgVcs extends AbstractVcs { } @Override - protected void start() throws VcsException { + protected void activate() { ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { if (ApplicationManager.getApplication().isUnitTestMode()) { From 78f8397d7e3b84831b5649f505f283d0bd6b0ce1 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Thu, 20 May 2010 13:21:19 +0400 Subject: [PATCH 14/23] EA-16845 - Throwable: FileManagerImpl.findDirectory: tagdir support refactored --- .../src/com/intellij/psi/impl/source/jsp/JspManager.java | 2 -- .../util/src/com/intellij/util/containers/ContainerUtil.java | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/java/jsp-spi/src/com/intellij/psi/impl/source/jsp/JspManager.java b/java/jsp-spi/src/com/intellij/psi/impl/source/jsp/JspManager.java index 14e8472811fc..4d8e88f29b2b 100644 --- a/java/jsp-spi/src/com/intellij/psi/impl/source/jsp/JspManager.java +++ b/java/jsp-spi/src/com/intellij/psi/impl/source/jsp/JspManager.java @@ -40,8 +40,6 @@ import java.util.Set; */ public abstract class JspManager implements IBaseJspManager { - public static final Key DIRECTORIES_KEY = Key.create("TagDirOriginalDirs"); - public static JspManager getInstance(@NotNull Project project) { return ServiceManager.getService(project, JspManager.class); } diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index 1ac5c1f664e8..5ad9423a6169 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -642,7 +642,7 @@ public class ContainerUtil { return result; } - public static List mapNotNull(T[] array, Function mapping) { + public static List mapNotNull(@NotNull T[] array, Function mapping) { return mapNotNull(Arrays.asList(array), mapping); } From b16b4d9dd17798a9086b5517eb03a688d17eb6e1 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 20 May 2010 13:40:24 +0400 Subject: [PATCH 15/23] PsiDocComment got an owner --- .../lang/java/JavaDocumentationProvider.java | 32 ++++++++++--------- .../psi/impl/compiled/ClsDocCommentImpl.java | 14 +++++--- .../source/javadoc/PsiDocCommentImpl.java | 24 ++++++++++---- .../intellij/psi/javadoc/PsiDocComment.java | 12 +++++++ .../groovydoc/psi/impl/GrDocCommentImpl.java | 1 + 5 files changed, 57 insertions(+), 26 deletions(-) diff --git a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java index 4cb54acf4a6b..535a36da14d5 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java @@ -430,22 +430,26 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext return buffer.toString(); } - public PsiComment findExistingDocComment(final PsiComment _element) { - PsiElement parentElement = _element.getParent(); - - return parentElement instanceof PsiDocCommentOwner ? ((PsiDocCommentOwner)parentElement).getDocComment() : null; + public PsiComment findExistingDocComment(final PsiComment comment) { + if (comment instanceof PsiDocComment) { + final PsiDocCommentOwner owner = ((PsiDocComment)comment).getOwner(); + if (owner != null) { + return owner.getDocComment(); + } + } + return null; } - public String generateDocumentationContentStub(PsiComment _element) { - PsiElement parentElement = _element.getParent(); - final Project project = _element.getProject(); + public String generateDocumentationContentStub(PsiComment _comment) { + final PsiDocCommentOwner commentOwner = ((PsiDocComment)_comment).getOwner(); + final Project project = commentOwner.getProject(); final StringBuilder builder = StringBuilderSpinAllocator.alloc(); try { - if (parentElement instanceof PsiMethod) { - PsiMethod psiMethod = (PsiMethod)parentElement; + final CodeDocumentationAwareCommenter commenter = (CodeDocumentationAwareCommenter)LanguageCommenters.INSTANCE + .forLanguage(commentOwner.getLanguage()); + if (commentOwner instanceof PsiMethod) { + PsiMethod psiMethod = (PsiMethod)commentOwner; final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); - final CodeDocumentationAwareCommenter commenter = (CodeDocumentationAwareCommenter)LanguageCommenters.INSTANCE - .forLanguage(parentElement.getLanguage()); final Map param2Description = new HashMap(); final PsiMethod[] superMethods = psiMethod.findSuperMethods(); for (PsiMethod superMethod : superMethods) { @@ -499,11 +503,9 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext builder.append(LINE_SEPARATOR); } } - else if (parentElement instanceof PsiClass) { - final PsiTypeParameterList typeParameterList = ((PsiClass)parentElement).getTypeParameterList(); + else if (commentOwner instanceof PsiClass) { + final PsiTypeParameterList typeParameterList = ((PsiClass)commentOwner).getTypeParameterList(); if (typeParameterList != null) { - final CodeDocumentationAwareCommenter commenter = (CodeDocumentationAwareCommenter)LanguageCommenters.INSTANCE - .forLanguage(parentElement.getLanguage()); createTypeParamsListComment(builder, project, commenter, typeParameterList); } } diff --git a/java/java-impl/src/com/intellij/psi/impl/compiled/ClsDocCommentImpl.java b/java/java-impl/src/com/intellij/psi/impl/compiled/ClsDocCommentImpl.java index c8b345eb626e..cc5d98a28476 100644 --- a/java/java-impl/src/com/intellij/psi/impl/compiled/ClsDocCommentImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/compiled/ClsDocCommentImpl.java @@ -15,7 +15,6 @@ */ package com.intellij.psi.impl.compiled; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; import com.intellij.psi.impl.source.tree.JavaDocElementType; import com.intellij.psi.impl.source.tree.TreeElement; @@ -26,12 +25,10 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; class ClsDocCommentImpl extends ClsElementImpl implements PsiDocComment, JavaTokenType, PsiJavaToken { - private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClsDocCommentImpl"); - - private final ClsElementImpl myParent; + private final PsiDocCommentOwner myParent; private final PsiDocTag[] myTags; - ClsDocCommentImpl(ClsElementImpl parent) { + ClsDocCommentImpl(PsiDocCommentOwner parent) { myParent = parent; PsiDocTag[] tags = new PsiDocTag[1]; @@ -63,10 +60,16 @@ class ClsDocCommentImpl extends ClsElementImpl implements PsiDocComment, JavaTok return myParent; } + public PsiDocCommentOwner getOwner() { + return myParent; + } + + @NotNull public PsiElement[] getDescriptionElements() { return EMPTY_ARRAY; } + @NotNull public PsiDocTag[] getTags() { return myTags; } @@ -76,6 +79,7 @@ class ClsDocCommentImpl extends ClsElementImpl implements PsiDocComment, JavaTok return getTags()[0]; } + @NotNull public PsiDocTag[] findTagsByName(@NonNls String name) { if (!name.equals("deprecated")) return PsiDocTag.EMPTY_ARRAY; return getTags(); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocCommentImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocCommentImpl.java index 3da36a9530bc..a061625051c5 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocCommentImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocCommentImpl.java @@ -18,10 +18,7 @@ package com.intellij.psi.impl.source.javadoc; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.psi.JavaElementVisitor; -import com.intellij.psi.JavaTokenType; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.impl.source.Constants; import com.intellij.psi.impl.source.PsiElementArrayConstructor; @@ -57,18 +54,32 @@ public class PsiDocCommentImpl extends LazyParseablePsiElement implements PsiDoc super(JavaDocElementType.DOC_COMMENT, text); } + public PsiDocCommentOwner getOwner() { + final PsiElement parent = getParent(); + if (parent instanceof PsiDocCommentOwner) { + final PsiDocCommentOwner owner = (PsiDocCommentOwner)parent; + if (owner.getDocComment() == this) { + return owner; + } + } + + return null; + } + + @NotNull public PsiElement[] getDescriptionElements() { - ArrayList array = new ArrayList(); + ArrayList array = new ArrayList(); for (ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()) { IElementType i = child.getElementType(); if (i == DOC_TAG) break; if (i != DOC_COMMENT_START && i != DOC_COMMENT_END && i != DOC_COMMENT_LEADING_ASTERISKS) { - array.add(child); + array.add(child.getPsi()); } } return array.toArray(new PsiElement[array.size()]); } + @NotNull public PsiDocTag[] getTags() { return getChildrenAsPsiElements(TAG_BIT_SET, PSI_TAG_ARRAY_CONSTRUCTOR); } @@ -92,6 +103,7 @@ public class PsiDocCommentImpl extends LazyParseablePsiElement implements PsiDoc return null; } + @NotNull public PsiDocTag[] findTagsByName(String name) { ArrayList array = new ArrayList(); PsiDocTag[] tags = getTags(); diff --git a/java/openapi/src/com/intellij/psi/javadoc/PsiDocComment.java b/java/openapi/src/com/intellij/psi/javadoc/PsiDocComment.java index 7710a8530059..83132393c6f8 100644 --- a/java/openapi/src/com/intellij/psi/javadoc/PsiDocComment.java +++ b/java/openapi/src/com/intellij/psi/javadoc/PsiDocComment.java @@ -16,13 +16,25 @@ package com.intellij.psi.javadoc; import com.intellij.psi.PsiComment; +import com.intellij.psi.PsiDocCommentOwner; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface PsiDocComment extends PsiComment { + @Nullable + PsiDocCommentOwner getOwner(); + + @NotNull PsiElement[] getDescriptionElements(); + + @NotNull PsiDocTag[] getTags(); + @Nullable PsiDocTag findTagByName(@NonNls String name); + + @NotNull PsiDocTag[] findTagsByName(@NonNls String name); } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocCommentImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocCommentImpl.java index a71b2b1342b0..a7507ea5b86b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocCommentImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocCommentImpl.java @@ -98,6 +98,7 @@ public class GrDocCommentImpl extends LazyParseablePsiElement implements GroovyD return list.toArray(new GrDocTag[list.size()]); } + @NotNull public PsiElement[] getDescriptionElements() { ArrayList array = new ArrayList(); for (PsiElement child = getFirstChild(); child != null; child = child.getNextSibling()) { From bbf612a6407a25a5d920f855032d2143a7835a81 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 13:49:18 +0400 Subject: [PATCH 16/23] Minor code reformatting --- .../src/com/intellij/formatting/AbstractBlockWrapper.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java index 56c7ccc48aa4..eb3260c8287a 100644 --- a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java +++ b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java @@ -168,12 +168,12 @@ public abstract class AbstractBlockWrapper { } public IndentData getChildOffset(AbstractBlockWrapper child, CodeStyleSettings.IndentOptions options, int targetBlockStartOffset) { - final boolean childOnNewLine = child.getWhiteSpace().containsLineFeeds(); + final boolean childStartsNewLine = child.getWhiteSpace().containsLineFeeds(); IndentImpl.Type childIndentType = child.getIndent().getType(); final IndentData childIndent; // Calculate child indent. - if (childOnNewLine + if (childStartsNewLine || (!getWhiteSpace().containsLineFeeds() && RELATIVE_INDENT_TYPES.contains(childIndentType) && indentAlreadyUsedBefore(child))) { childIndent = getIndent(options, child, targetBlockStartOffset); @@ -184,7 +184,7 @@ public abstract class AbstractBlockWrapper { // Use child indent if it's absolute and the child is contained on new line. - if (childOnNewLine) { + if (childStartsNewLine) { if (child.getIndent().isAbsolute()) { myFlags &= ~CAN_USE_FIRST_CHILD_INDENT_AS_BLOCK_INDENT; AbstractBlockWrapper current = this; From 29c52df9d0f8fb490deefce23c03c71d74573350 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 13:50:30 +0400 Subject: [PATCH 17/23] IDEA-53778 Indent in a method body shouldn't be defined by indent of the method comment Common functionality for synthetic blocks construction is moved to this class from CodeBlockBlock. That is done in order to provide access to it from BlockContainingJavaBlock class. --- .../psi/formatter/java/AbstractJavaBlock.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) 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 698baf09ceac..d72cf39fc2fb 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 @@ -213,6 +213,10 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } } + protected static boolean isRBrace(final ASTNode child) { + return child.getElementType() == ElementType.RBRACE; + } + public Spacing getSpacing(Block child1, Block child2) { return JavaSpacePropertyProcessor.getSpacing(getTreeNode(child2), mySettings); } @@ -1080,4 +1084,32 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo return JavaBlockUtil.mayShiftIndentInside(myNode); } + @Nullable + protected ASTNode composeCodeBlock(final ArrayList result, ASTNode child, final Indent indent, final int childrenIndent) { + final ArrayList localResult = new ArrayList(); + processChild(localResult, child, null, null, Indent.getNoneIndent()); + child = child.getTreeNext(); + while (child != null) { + if (!FormatterUtil.containsWhiteSpacesOnly(child)) { + final boolean rBrace = isRBrace(child); + final Indent childIndent = rBrace ? Indent.getNoneIndent() : getCodeBlockInternalIndent(childrenIndent); + child = processChild(localResult, child, null, null, childIndent); + if (rBrace) { + result.add(createCodeBlockBlock(localResult, indent, childrenIndent)); + return child; + } + } + if (child != null) { + child = child.getTreeNext(); + } + } + result.add(createCodeBlockBlock(localResult, indent, childrenIndent)); + return null; + } + + private SyntheticCodeBlock createCodeBlockBlock(final ArrayList localResult, final Indent indent, final int childrenIndent) { + final SyntheticCodeBlock result = new SyntheticCodeBlock(localResult, null, getSettings(), indent, null); + result.setChildAttributes(new ChildAttributes(getCodeBlockInternalIndent(childrenIndent), null)); + return result; + } } From f499b49e8425ca294e4024cab264fbbfbc80f83d Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 13:51:04 +0400 Subject: [PATCH 18/23] IDEA-53778 Indent in a method body shouldn't be defined by indent of the method comment Common functionality for synthetic blocks construction is moved to AbstractJavaBlock from this class. That is done in order to provide access to it from BlockContainingJavaBlock class. --- .../psi/formatter/java/CodeBlockBlock.java | 35 +------------------ 1 file changed, 1 insertion(+), 34 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 f93962a6b00c..1e448bb8e403 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 @@ -86,7 +86,7 @@ public class CodeBlockBlock extends AbstractJavaBlock { child = processCaseAndStatementAfter(result, child, childAlignment, childWrap, indent); } else if (myNode.getElementType() == ElementType.CLASS && child.getElementType() == ElementType.LBRACE) { - child = composeCodeBlock(result, child, getCodeBlockExternalIndent()); + child = composeCodeBlock(result, child, getCodeBlockExternalIndent(), myChildrenIndent); } else { child = processChild(result, child, childAlignment, childWrap, indent); @@ -98,35 +98,6 @@ 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()); - child = child.getTreeNext(); - while (child != null) { - if (!FormatterUtil.containsWhiteSpacesOnly(child)) { - final boolean rBrace = isRBrace(child); - final Indent childIndent = rBrace ? Indent.getNoneIndent() : getCodeBlockInternalIndent(myChildrenIndent); - child = processChild(localResult, child, null, null, childIndent); - if (rBrace) { - result.add(createCodeBlockBlock(localResult, indent)); - return child; - } - } - if (child != null) { - child = child.getTreeNext(); - } - } - result.add(createCodeBlockBlock(localResult, indent)); - return null; - } - - private SyntheticCodeBlock createCodeBlockBlock(final ArrayList localResult, final Indent indent) { - final SyntheticCodeBlock result = new SyntheticCodeBlock(localResult, null, getSettings(), indent, null); - result.setChildAttributes(new ChildAttributes(getCodeBlockInternalIndent(myChildrenIndent), null)); - return result; - } - @Nullable private ASTNode processCaseAndStatementAfter(final ArrayList result, ASTNode child, @@ -253,10 +224,6 @@ public class CodeBlockBlock extends AbstractJavaBlock { } } - private static boolean isRBrace(final ASTNode child) { - return child.getElementType() == ElementType.RBRACE; - } - @Override @NotNull public ChildAttributes getChildAttributes(final int newChildIndex) { From 0f51880e1c5683f9105ac06fa870375ab2890cef Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 13:51:52 +0400 Subject: [PATCH 19/23] IDEA-53778 Indent in a method body shouldn't be defined by indent of the method comment Method block construction algorithm is revised in order to create different blocks for pre-method comments and method itself --- .../java/BlockContainingJavaBlock.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) 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 06b6c1603d01..5ffc1394cedb 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 @@ -17,6 +17,7 @@ package com.intellij.psi.formatter.java; import com.intellij.formatting.*; import com.intellij.lang.ASTNode; +import com.intellij.psi.JavaTokenType; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.impl.source.tree.ElementType; @@ -52,6 +53,7 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{ private void buildChildren(final ArrayList result, final Alignment childAlignment, final Wrap childWrap) { ASTNode child = myNode.getFirstChildNode(); + ASTNode prevChild = null; int state = BEFORE_FIRST; @@ -60,7 +62,26 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{ final Indent indent = calcIndent(child, state); myIndentsBefore.add(calcIndentBefore(child, state)); state = calcNewState(child, state); - child = processChild(result, child, childAlignment, childWrap, indent); + + // The general idea is that it's possible that there are comment lines before method declaration line and that they have + // different indents. Example: + // + // // This is comment before method + // void foo() {} + // + // We want to have the comment and method as distinct blocks then in order to correctly process indentation for inner method + // elements. See IDEA-53778 for example of situation when it is significant. + if (prevChild != null && myNode.getElementType() == ElementType.METHOD + && JavaTokenType.COMMENT_BIT_SET.contains(prevChild.getElementType()) + && !JavaTokenType.COMMENT_BIT_SET.contains(child.getElementType())) + { + prevChild = child; + child = composeCodeBlock(result, child, Indent.getNoneIndent(), 0); + } + else { + prevChild = child; + child = processChild(result, child, childAlignment, childWrap, indent); + } for (int i = myIndentsBefore.size(); i < result.size(); i++) { myIndentsBefore.add(Indent.getContinuationIndent()); } From 89cebd04fd385ed36900b3e4ea17750a953b28ae Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 13:52:29 +0400 Subject: [PATCH 20/23] IDEA-53778 Indent in a method body shouldn't be defined by indent of the method comment Corresponding test is added --- ...ntLinesTest.java => JavaIndenterTest.java} | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) rename java/java-tests/testSrc/com/intellij/psi/formatter/java/{AutoIndentLinesTest.java => JavaIndenterTest.java} (57%) diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/AutoIndentLinesTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaIndenterTest.java similarity index 57% rename from java/java-tests/testSrc/com/intellij/psi/formatter/java/AutoIndentLinesTest.java rename to java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaIndenterTest.java index c1a1936ae0d2..6961877d7bae 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/AutoIndentLinesTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaIndenterTest.java @@ -22,7 +22,9 @@ import com.intellij.util.IncorrectOperationException; * @author Denis Zhdanov * @since May 11, 2010 5:30:28 PM */ -public class AutoIndentLinesTest extends AbstractJavaFormatterTest { +public class JavaIndenterTest extends AbstractJavaFormatterTest { + + private static final String CARET_TOKEN = ""; public void testIndentAlignedMethodParameter() { // Inspired by IDEA-22020 @@ -41,7 +43,7 @@ public class AutoIndentLinesTest extends AbstractJavaFormatterTest { int end = initial.indexOf("\n", start); myTextRange = new TextRange(start, end); - doTextTest(Action.INDENT, initial, + doTextTest(initial, "class BrokenAlignment {\n" + " public\n" + "\tstatic int foo(String a, String b, String c,\n" + @@ -52,8 +54,41 @@ public class AutoIndentLinesTest extends AbstractJavaFormatterTest { ); } + public void testMethodBodyShiftedToComment() { + // Inspired by IDEA-53778 + + doTextTest( + "class Test {\n" + + " // some comment\n" + + " public void doSmth(int[] p) {\n" + + "\n" + + " }" + + "}", + + "class Test {\n" + + " // some comment\n" + + " public void doSmth(int[] p) {\n" + + " \n" + + " }" + + "}"); + } + @Override public void doTextTest(String text, String textAfter) throws IncorrectOperationException { - doTextTest(Action.INDENT, text, textAfter); + doTextTest(Action.INDENT, adjustTextIfNecessary(text), textAfter); + } + + private String adjustTextIfNecessary(String text) { + int caretIndex = text.indexOf(CARET_TOKEN); + if (caretIndex < 0) { + return text; + } + + if (caretIndex < text.length() && text.indexOf(CARET_TOKEN, caretIndex + 1) >= 0) { + fail(String.format("Invalid indentation test 'before' text - it contains more than one caret meta-token (%s). Text: %n%s", + CARET_TOKEN, text)); + } + myTextRange = new TextRange(caretIndex, caretIndex); + return text.substring(0, caretIndex) + text.substring(caretIndex + CARET_TOKEN.length()); } } From dd0f5605f472f054ab7e14addea61d35db589580 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 15:02:05 +0400 Subject: [PATCH 21/23] EA-20331 - NPE: JavaSmartEnterProcessor.reformat Check for null is introduced --- .../editorActions/smartEnter/JavaSmartEnterProcessor.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java index 2b458cb77466..8efc372f68be 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java @@ -154,6 +154,9 @@ public class JavaSmartEnterProcessor extends SmartEnterProcessor { @Override protected void reformat(PsiElement atCaret) throws IncorrectOperationException { + if (atCaret == null) { + return; + } PsiElement parent = atCaret.getParent(); if (parent instanceof PsiCodeBlock) { final PsiCodeBlock block = (PsiCodeBlock) parent; From 2e487d86dde1bc40abac0fc580e4eeaef188b608 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 20 May 2010 15:08:32 +0400 Subject: [PATCH 22/23] add new lines, if it is a block tag (fix WI-1381) --- .../template/CustomTemplateCallback.java | 29 +++++++++++ .../zencoding/XmlZenCodingInterpreter.java | 48 ++++++++++++------- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java b/platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java index 3dcebcb7127c..d09e0fbeaba3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java @@ -222,6 +222,35 @@ public class CustomTemplateCallback { myBuilder.insertText(offset, text); } + public void insertNewLine() { + myBuilder.insertText(myOffset, "\n"); + myOffset++; + } + + public boolean newLineBefore() { + int i = myOffset - 1; + CharSequence text = myBuilder.getText(); + while (i >= 0 && Character.isWhitespace(text.charAt(i))) { + if (text.charAt(i) == '\n') { + return true; + } + i--; + } + return i < 0; + } + + public boolean newLineAfter() { + int i = myOffset; + CharSequence text = myBuilder.getText(); + while (i < text.length() && Character.isWhitespace(text.charAt(i))) { + if (text.charAt(i) == '\n') { + return true; + } + i++; + } + return i == text.length(); + } + public void deleteTemplateKey(String key) { int caretAt = myEditor.getCaretModel().getOffset(); myEditor.getDocument().deleteString(caretAt - key.length(), caretAt); diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingInterpreter.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingInterpreter.java index 3600106a09cf..21274dd639f9 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingInterpreter.java +++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingInterpreter.java @@ -29,6 +29,7 @@ import com.intellij.psi.xml.XmlTokenType; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; import com.intellij.util.containers.IntArrayList; +import com.intellij.xml.util.HtmlUtil; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -310,27 +311,38 @@ class XmlZenCodingInterpreter { if (token instanceof XmlTemplateToken && token.getTemplate() != null) { XmlTemplateToken xmlTemplateToken = (XmlTemplateToken)token; List> attr2value = new ArrayList>(xmlTemplateToken.getAttribute2Value()); - if (attr2value.size() > 0 || XmlZenCodingTemplate.isTrueXml(callback)) { - TemplateImpl modifiedTemplate = token.getTemplate().copy(); - XmlTag tag = xmlTemplateToken.getTag(); - if (tag != null) { - for (Iterator> iterator = attr2value.iterator(); iterator.hasNext();) { - Pair pair = iterator.next(); - if (tag.getAttribute(pair.first) != null) { - tag.setAttribute(pair.first, ZenCodingUtil.getValue(pair, numberInIteration)); - iterator.remove(); - } + TemplateImpl modifiedTemplate = token.getTemplate().copy(); + XmlTag tag = xmlTemplateToken.getTag(); + if (tag != null) { + for (Iterator> iterator = attr2value.iterator(); iterator.hasNext();) { + Pair pair = iterator.next(); + if (tag.getAttribute(pair.first) != null) { + tag.setAttribute(pair.first, ZenCodingUtil.getValue(pair, numberInIteration)); + iterator.remove(); } - String s = filterXml(tag, callback, filter); - assert s != null; - modifiedTemplate.setString(s); - removeVariablesWhichHasNoSegment(modifiedTemplate); - Map predefinedValues = buildPredefinedValues(attr2value, numberInIteration, callback); - callback.expandTemplate(modifiedTemplate, predefinedValues); - return; } + String s = filterXml(tag, callback, filter); + assert s != null; + if (HtmlUtil.isHtmlBlockTagL(tag.getName())) { + boolean newLineBefore = callback.newLineBefore(); + boolean newLineAfter = callback.newLineAfter(); + if (!newLineBefore || !newLineAfter) { + StringBuilder builder = new StringBuilder(); + if (!newLineBefore) { + builder.append('\n'); + } + builder.append(s); + if (!newLineAfter) { + builder.append('\n'); + } + s = builder.toString(); + } + } + modifiedTemplate.setString(s); + removeVariablesWhichHasNoSegment(modifiedTemplate); + Map predefinedValues = buildPredefinedValues(attr2value, numberInIteration, callback); + callback.expandTemplate(modifiedTemplate, predefinedValues); } - callback.expandTemplate(token.getTemplate(), null); } else { // for CSS From dde139215764956b3d3afa0406cc999fa287922e Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 20 May 2010 15:12:31 +0400 Subject: [PATCH 23/23] IDEA-42167 Reformat code works wrong Test data is revised in accordance with corrected algorithm --- .../testData/refactoring/changeSignature/SCR40895.java | 2 +- .../testData/refactoring/changeSignature/SCR40895_after.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java-tests/testData/refactoring/changeSignature/SCR40895.java b/java/java-tests/testData/refactoring/changeSignature/SCR40895.java index 05e4785c2e7c..f2e1889bece5 100644 --- a/java/java-tests/testData/refactoring/changeSignature/SCR40895.java +++ b/java/java-tests/testData/refactoring/changeSignature/SCR40895.java @@ -1,7 +1,7 @@ class X { /** - * Has a method called {@link #mymethod(int,int)}. + * Has a method called {@link #mymethod(int, int)}. */ public class TestRefactorLink { public void mymethod(int y, int z) { } diff --git a/java/java-tests/testData/refactoring/changeSignature/SCR40895_after.java b/java/java-tests/testData/refactoring/changeSignature/SCR40895_after.java index 1a0291659eeb..cc8388fb3f1f 100644 --- a/java/java-tests/testData/refactoring/changeSignature/SCR40895_after.java +++ b/java/java-tests/testData/refactoring/changeSignature/SCR40895_after.java @@ -1,7 +1,7 @@ class X { /** - * Has a method called {@link #mymethod(int,boolean)}. + * Has a method called {@link #mymethod(int, boolean)}. */ public class TestRefactorLink { public void mymethod(int y, boolean b) { }