infer alignments for right curly braces before creating formatting blocks

This commit is contained in:
Maxim.Medvedev
2011-12-20 12:46:07 +04:00
parent 48328f2dd3
commit c6d5e2a85a
6 changed files with 76 additions and 109 deletions
@@ -82,7 +82,7 @@ public class GeeseUtil {
}
@Nullable
static Alignment calculateRBraceAlignment(PsiElement rBrace, Map<PsiElement, Alignment> alignments, Map<PsiElement, GroovyBlock> blocks) {
static Alignment calculateRBraceAlignment(PsiElement rBrace, Map<PsiElement, Alignment> alignments) {
int leadingBraceCount = 0;
PsiElement next;
@@ -146,11 +146,7 @@ public class GeeseUtil {
Alignment alignment = alignments.get(cur);
if (alignment == null) {
final GroovyBlock block = blocks.get(cur);
alignment = Alignment.createAlignment(true);
if (block != null) {
block.setAlignment(alignment);
}
alignments.put(cur, alignment);
}
return alignment;
@@ -55,7 +55,7 @@ import java.util.Map;
*
* @author ilyas
*/
public abstract class GroovyBlock implements Block, GroovyElementTypes, ASTBlock {
public class GroovyBlock implements Block, GroovyElementTypes, ASTBlock {
final protected ASTNode myNode;
protected Alignment myAlignment;
final protected Indent myIndent;
@@ -63,7 +63,6 @@ public abstract class GroovyBlock implements Block, GroovyElementTypes, ASTBlock
final protected CommonCodeStyleSettings mySettings;
final protected GroovyCodeStyleSettings myGroovySettings;
final protected Map<PsiElement, Alignment> myInnerAlignments;
final protected Map<PsiElement, GroovyBlock> myBlocks;
protected List<Block> mySubBlocks = null;
@@ -73,12 +72,10 @@ public abstract class GroovyBlock implements Block, GroovyElementTypes, ASTBlock
@Nullable final Wrap wrap,
final CommonCodeStyleSettings settings,
GroovyCodeStyleSettings groovySettings,
@NotNull Map<PsiElement, Alignment> innerAlignments, Map<PsiElement, GroovyBlock> blocks) {
@NotNull Map<PsiElement, Alignment> innerAlignments) {
myNode = node;
myBlocks = blocks;
if (groovySettings.USE_FLYING_GEESE_BRACES) {
PsiElement psi = myNode.getPsi();
myBlocks.put(psi, this);
if (alignment == null) {
alignment = innerAlignments.get(psi);
}
@@ -119,8 +116,12 @@ public abstract class GroovyBlock implements Block, GroovyElementTypes, ASTBlock
}
@NotNull
@Override
public List<Block> getSubBlocks() {
return mySubBlocks;
if (mySubBlocks == null) {
mySubBlocks = new GroovyBlockGenerator(this).generateSubBlocks();
}
return mySubBlocks;
}
@Nullable
@@ -228,10 +229,6 @@ public abstract class GroovyBlock implements Block, GroovyElementTypes, ASTBlock
return isIncomplete(myNode);
}
public void setAlignment(Alignment alignment) {
myAlignment = alignment;
}
/**
* @param node Tree node
* @return true if node is incomplete
@@ -82,7 +82,6 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
private final Wrap myWrap;
private final CommonCodeStyleSettings mySettings;
private final Map<PsiElement,Alignment> myInnerAlignments;
private final Map<PsiElement,GroovyBlock> myBlocks;
private final GroovyCodeStyleSettings myGroovySettings;
public GroovyBlockGenerator(GroovyBlock block) {
@@ -93,7 +92,6 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
mySettings = myBlock.getSettings();
myInnerAlignments = myBlock.getInnerAlignments();
myGroovySettings = myBlock.getGroovySettings();
myBlocks = myBlock.myBlocks;
}
@@ -136,8 +134,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
for (ASTNode childNode : children) {
if (childNode.getTextRange().getLength() > 0) {
final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
subBlocks.add(new GroovySimpleBlock(childNode, myAlignment, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks));
subBlocks.add(new GroovyBlock(childNode, myAlignment, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
}
}
return subBlocks;
@@ -158,8 +155,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
final Alignment newAlignment = mustAlign(blockPsi, astNodes) ? Alignment.createAlignment() : null;
for (ASTNode childNode : astNodes) {
final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
subBlocks.add(new GroovySimpleBlock(childNode, isKeyword(childNode) ? null : newAlignment, indent, myWrap, mySettings, myGroovySettings,
myInnerAlignments, myBlocks));
subBlocks.add(new GroovyBlock(childNode, isKeyword(childNode) ? null : newAlignment, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
}
return subBlocks;
}
@@ -172,8 +168,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
for (ASTNode childNode : children) {
final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
Alignment alignmentToUse = classLevel ? myAlignment : myInnerAlignments.get(childNode.getPsi());
subBlocks.add(new GroovySimpleBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks));
subBlocks.add(new GroovyBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
}
return subBlocks;
}
@@ -182,8 +177,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
final ArrayList<Block> subBlocks = new ArrayList<Block>();
for (ASTNode childNode : visibleChildren(myNode)) {
final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
subBlocks.add(new GroovySimpleBlock(childNode, myInnerAlignments.get(childNode.getPsi()), indent, myWrap, mySettings, myGroovySettings,
myInnerAlignments, myBlocks));
subBlocks.add(new GroovyBlock(childNode, myInnerAlignments.get(childNode.getPsi()), indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
}
return subBlocks;
}
@@ -232,9 +226,9 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
}
}
}
else if (GeeseUtil.isClosureRBrace(psi) && myGroovySettings.USE_FLYING_GEESE_BRACES) {
/*else if (GeeseUtil.isClosureRBrace(psi) && myGroovySettings.USE_FLYING_GEESE_BRACES) {
myInnerAlignments.put(psi, GeeseUtil.calculateRBraceAlignment(psi, myInnerAlignments, myBlocks));
}
}*/
else {
if (psi instanceof PsiComment) {
PsiElement prev = psi.getPrevSibling();
@@ -325,22 +319,19 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
final int start = myNode.getTextRange().getStartOffset();
final int end = myNode.getTextRange().getEndOffset();
subBlocks.add(new GroovySimpleBlock(myNode, myAlignment, Indent.getNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks) {
subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
@NotNull
public TextRange getTextRange() {
return new TextRange(start, start + 3);
}
});
subBlocks.add(new GroovySimpleBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks) {
subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
@NotNull
public TextRange getTextRange() {
return new TextRange(start + 3, end - 3);
}
});
subBlocks.add(new GroovySimpleBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks) {
subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
@NotNull
public TextRange getTextRange() {
return new TextRange(end - 3, end);
@@ -354,15 +345,13 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
final int start = myNode.getTextRange().getStartOffset();
final int end = myNode.getTextRange().getEndOffset();
subBlocks.add(new GroovySimpleBlock(myNode, myAlignment, Indent.getNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks) {
subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
@NotNull
public TextRange getTextRange() {
return new TextRange(start, start + 3);
}
});
subBlocks.add(new GroovySimpleBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks) {
subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
@NotNull
public TextRange getTextRange() {
return new TextRange(start + 3, end);
@@ -444,8 +433,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
PsiElement psi = childNode.getPsi();
if (!(psi instanceof GrBinaryExpression)) {
Alignment alignmentToUse = op == psi ? myInnerAlignments.get(op) : alignment;
list.add(new GroovySimpleBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks));
list.add(new GroovyBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
}
}
if (myExpr.getRightOperand() instanceof GrBinaryExpression) {
@@ -474,8 +462,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
}
if (i < grandChildren.size()) {
LOG.assertTrue(nameElement == grandChildren.get(i).getPsi());
list.add(new MethodCallWithoutQualifierBlock(nameElement, null, myWrap, mySettings, myGroovySettings, topLevel, children, elem,
myInnerAlignments, myBlocks));
list.add(new MethodCallWithoutQualifierBlock(nameElement, null, myWrap, mySettings, myGroovySettings, topLevel, children, elem, myInnerAlignments));
}
return;
}
@@ -496,7 +483,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
else {
Alignment alignmentToUse = myInnerAlignments.get(fst.getPsi());
Indent indent = Indent.getContinuationWithoutFirstIndent();
list.add(new GroovySimpleBlock(fst, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments, myBlocks));
list.add(new GroovyBlock(fst, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
}
addNestedChildrenSuffix(list, alignment, topLevel, children, limit);
}
@@ -510,7 +497,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
Indent.getContinuationWithoutFirstIndent() :
Indent.getNoneIndent();
Alignment alignmentToUse = TokenSets.DOTS.contains(type) ? alignment : myInnerAlignments.get(childNode.getPsi());
list.add(new GroovySimpleBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments, myBlocks));
list.add(new GroovyBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
}
}
}
@@ -21,6 +21,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiRecursiveElementVisitor;
import com.intellij.psi.TokenType;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
@@ -36,6 +37,8 @@ import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import java.util.Map;
/**
* @author ilyas
*/
@@ -50,9 +53,24 @@ public class GroovyFormattingModelBuilder implements FormattingModelBuilder {
assert astNode != null;
CommonCodeStyleSettings groovySettings = settings.getCommonSettings(GroovyFileType.GROOVY_LANGUAGE);
GroovyCodeStyleSettings customSettings = settings.getCustomSettings(GroovyCodeStyleSettings.class);
final GroovyBlock block = new GroovySimpleBlock(astNode, null, Indent.getAbsoluteNoneIndent(), null, groovySettings, customSettings,
CollectionFactory.<PsiElement, Alignment>hashMap(),
CollectionFactory.<PsiElement, GroovyBlock>hashMap());
final Map<PsiElement, Alignment> innerAlignments = CollectionFactory.hashMap();
if (customSettings.USE_FLYING_GEESE_BRACES) {
element.accept(new PsiRecursiveElementVisitor() {
@Override
public void visitElement(PsiElement element) {
if (GeeseUtil.isClosureRBrace(element)) {
final Alignment alignment = GeeseUtil.calculateRBraceAlignment(element, innerAlignments);
innerAlignments.put(element, alignment);
}
else {
super.visitElement(element);
}
}
});
}
final GroovyBlock block =
new GroovyBlock(astNode, null, Indent.getAbsoluteNoneIndent(), null, groovySettings, customSettings, innerAlignments);
return new GroovyFormattingModel(containingFile, block, FormattingDocumentModelImpl.createOn(containingFile));
}
@@ -1,43 +0,0 @@
/*
* Copyright 2000-2011 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 org.jetbrains.plugins.groovy.formatter;
import com.intellij.formatting.Alignment;
import com.intellij.formatting.Indent;
import com.intellij.formatting.Wrap;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
/**
* @author Max Medvedev
*/
public class GroovySimpleBlock extends GroovyBlock {
public GroovySimpleBlock(@NotNull ASTNode node,
@Nullable Alignment alignment,
@NotNull Indent indent,
@Nullable Wrap wrap,
CommonCodeStyleSettings settings,
GroovyCodeStyleSettings groovySettings,
@NotNull Map<PsiElement, Alignment> innerAlignments, Map<PsiElement, GroovyBlock> blocks) {
super(node, alignment, indent, wrap, settings, groovySettings, innerAlignments, blocks);
mySubBlocks = new GroovyBlockGenerator(this).generateSubBlocks();
}
}
@@ -33,36 +33,48 @@ import java.util.Map;
* @author peter
*/
public class MethodCallWithoutQualifierBlock extends GroovyBlock {
private final TextRange myRange;
private final PsiElement myNameElement;
private final boolean myTopLevel;
private final List<ASTNode> myChildren;
private final PsiElement myElem;
protected MethodCallWithoutQualifierBlock(PsiElement nameElement,
Alignment alignment,
Wrap wrap,
CommonCodeStyleSettings settings,
GroovyCodeStyleSettings groovySettings,
boolean topLevel,
List<ASTNode> children,
PsiElement elem,
Map<PsiElement, Alignment> innerAlignments, Map<PsiElement, GroovyBlock> blocks) {
super(nameElement.getNode(), alignment, Indent.getContinuationWithoutFirstIndent(), wrap, settings, groovySettings, innerAlignments,blocks);
myRange = new TextRange(nameElement.getTextRange().getStartOffset(), elem.getTextRange().getEndOffset());
public MethodCallWithoutQualifierBlock(PsiElement nameElement,
Alignment alignment,
Wrap wrap,
CommonCodeStyleSettings settings,
GroovyCodeStyleSettings groovySettings,
boolean topLevel,
List<ASTNode> children,
PsiElement elem,
Map<PsiElement, Alignment> innerAlignments) {
super(nameElement.getNode(), alignment, Indent.getContinuationWithoutFirstIndent(), wrap, settings, groovySettings, innerAlignments);
myNameElement = nameElement;
myTopLevel = topLevel;
myChildren = children;
myElem = elem;
}
mySubBlocks = new ArrayList<Block>();
final GroovySimpleBlock first =
new GroovySimpleBlock(nameElement.getNode(), myInnerAlignments.get(nameElement), Indent.getContinuationWithoutFirstIndent(), myWrap,
mySettings, myGroovySettings, myInnerAlignments, myBlocks);
mySubBlocks.add(first);
new GroovyBlockGenerator(this).addNestedChildrenSuffix(mySubBlocks, myAlignment, topLevel, children, children.size());
@NotNull
@Override
public List<Block> getSubBlocks() {
if (mySubBlocks == null) {
mySubBlocks = new ArrayList<Block>();
mySubBlocks.add(
new GroovyBlock(myNameElement.getNode(), myInnerAlignments.get(myNameElement), Indent.getContinuationWithoutFirstIndent(), myWrap,
mySettings, myGroovySettings, myInnerAlignments));
new GroovyBlockGenerator(this).addNestedChildrenSuffix(mySubBlocks, myAlignment, myTopLevel, myChildren, myChildren.size());
}
return mySubBlocks;
}
@NotNull
@Override
public TextRange getTextRange() {
return myRange;
return new TextRange(myNameElement.getTextRange().getStartOffset(), myElem.getTextRange().getEndOffset());
}
@Override
public boolean isLeaf() {
return false;
}
}
}