From 7f5841519f901e954fd507ddc6a41da8b0fc397a Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 5 Aug 2016 12:44:03 +0300 Subject: [PATCH] [psi-based formatting] place space before empty element if it's left bound and first child of it's parent (since bounds works only for child on the same level), fixes IDEA-158868 --- .../formatter/java/JavaPsiFormattingTest.java | 59 +++++++++++++++++++ .../intellij/psi/formatter/FormatterUtil.java | 10 +++- 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaPsiFormattingTest.java diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaPsiFormattingTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaPsiFormattingTest.java new file mode 100644 index 000000000000..66fbdf8891d4 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaPsiFormattingTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2016 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.openapi.application.WriteAction; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.util.Ref; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiExpression; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiIfStatement; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.impl.DebugUtil; +import com.intellij.psi.util.PsiTreeUtil; + +public class JavaPsiFormattingTest extends AbstractJavaFormatterTest { + + public void testReferenceExpressionSpaceInsertion() { + String text = "if(x&y);"; + PsiFile file = createFile("A.java", "class C{{\n" + text + "\n}}"); + PsiElement element = file.findElementAt(file.getText().indexOf(text)); + PsiIfStatement statement = PsiTreeUtil.getParentOfType(element, PsiIfStatement.class); + assertNotNull(statement); + + Ref result = Ref.create(); + CommandProcessor.getInstance().executeCommand(getProject(), () -> WriteAction.run( + () -> result.set(CodeStyleManager.getInstance(getProject()).reformat(statement)) + ), "", null); + + PsiExpression expr = ((PsiIfStatement)result.get()).getCondition(); + assertEquals("PsiBinaryExpression:x & y\n" + + " PsiReferenceExpression:x\n" + + " PsiReferenceParameterList\n" + + " \n" + + " PsiIdentifier:x('x')\n" + + " PsiWhiteSpace(' ')\n" + + " PsiJavaToken:AND('&')\n" + + " PsiWhiteSpace(' ')\n" + + " PsiReferenceExpression:y\n" + + " PsiReferenceParameterList\n" + + " \n" + + " PsiIdentifier:y('y')\n", + DebugUtil.psiToString(expr, false)); + } + +} 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 4b6e96fcc1c7..fd43a86453b6 100644 --- a/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java @@ -378,7 +378,7 @@ public class FormatterUtil { if (treePrev.getElementType() == TokenType.WHITE_SPACE) { return treePrev; } - else if (treePrev.getTextLength() == 0 && !treePrev.getElementType().isLeftBound()) { + else if (treePrev.getTextLength() == 0 && isSpaceBeforeEmptyElement(treePrev)) { return getWsCandidate(treePrev); } else { @@ -395,6 +395,14 @@ public class FormatterUtil { } } + private static boolean isSpaceBeforeEmptyElement(ASTNode node) { + if (node.getElementType().isLeftBound()) { + final ASTNode parent = node.getTreeParent(); + return parent != null && parent.getFirstChildNode() == node; + } + return true; + } + private static StringBuilder createNewLeafChars(final ASTNode leafElement, final TextRange textRange, final String whiteSpace) { final TextRange elementRange = leafElement.getTextRange(); final String elementText = leafElement.getText();