EA-31488 - assert: AbstractBlockAlignmentProcessor.applyAlignment

This commit is contained in:
Maxim.Medvedev
2011-12-19 13:55:04 +04:00
parent 043a5a8125
commit 50839bb249
7 changed files with 152 additions and 89 deletions
@@ -82,7 +82,7 @@ public class GeeseUtil {
}
@Nullable
static Alignment calculateRBraceAlignment(PsiElement rBrace, Map<PsiElement, Alignment> alignments) {
static Alignment calculateRBraceAlignment(PsiElement rBrace, Map<PsiElement, Alignment> alignments, Map<PsiElement, GroovyBlock> blocks) {
int leadingBraceCount = 0;
PsiElement next;
@@ -121,21 +121,36 @@ public class GeeseUtil {
cur = PsiTreeUtil.getDeepestFirst(cur);
while (!PsiUtil.isNewLine(next = PsiTreeUtil.prevLeaf(cur, true))) {
if (next == null) break;
if (next.getNode().getElementType() == TokenType.WHITE_SPACE && PsiTreeUtil.prevLeaf(next) == null) break; //if cur is first word in the text, whitespace could be before it
if (next.getNode().getElementType() == TokenType.WHITE_SPACE && PsiTreeUtil.prevLeaf(next) == null) {
break; //if cur is first word in the text, whitespace could be before it
}
cur = next;
}
int startOffset = cur.getTextRange().getStartOffset();
int endOffset=rBrace.getTextRange().getStartOffset();
int endOffset = rBrace.getTextRange().getStartOffset();
if (rBrace.getContainingFile().getText().substring(startOffset, endOffset).indexOf('\n') < 0) {
return null;
}
//PsiElement statement = PsiUtil.findEnclosingStatement(parent);
while (true) {
final PsiElement p = cur.getParent();
if (p != null && p.getTextOffset() == cur.getTextOffset()) {
cur = p;
}
else {
break;
}
}
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;
@@ -25,7 +25,6 @@ import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.tree.ILazyParseableElementType;
import com.intellij.util.containers.CollectionFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.formatter.processors.GroovyIndentProcessor;
@@ -56,48 +55,38 @@ import java.util.Map;
*
* @author ilyas
*/
public class GroovyBlock implements Block, GroovyElementTypes, ASTBlock {
public abstract class GroovyBlock implements Block, GroovyElementTypes, ASTBlock {
final protected ASTNode myNode;
final protected Alignment myAlignment;
protected Alignment myAlignment;
final protected Indent myIndent;
final protected Wrap myWrap;
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;
public GroovyBlock(@NotNull final ASTNode node,
@Nullable final Alignment alignment,
@NotNull final Indent indent,
@Nullable final Wrap wrap,
final CommonCodeStyleSettings settings,
GroovyCodeStyleSettings groovySettings
) {
this(node, alignment, indent, wrap, settings, groovySettings, CollectionFactory.<PsiElement, Alignment>hashMap());
}
public GroovyBlock(@NotNull final ASTNode node,
@Nullable Alignment alignment,
@NotNull final Indent indent,
@Nullable final Wrap wrap,
final CommonCodeStyleSettings settings,
GroovyCodeStyleSettings groovySettings,
@NotNull Map<PsiElement, Alignment> innerAlignments) {
@NotNull Map<PsiElement, Alignment> innerAlignments, Map<PsiElement, GroovyBlock> blocks) {
myNode = node;
if (groovySettings.USE_FLYING_GEESE_BRACES && isLeaf()) {
myBlocks = blocks;
if (groovySettings.USE_FLYING_GEESE_BRACES) {
PsiElement psi = myNode.getPsi();
if (alignment == null) alignment = innerAlignments.get(psi);
if (alignment == null) alignment = Alignment.createAlignment(true);
myAlignment = alignment;
innerAlignments.put(psi, myAlignment);
myBlocks.put(psi, this);
if (alignment == null) {
alignment = innerAlignments.get(psi);
}
else {
innerAlignments.put(psi, alignment);
}
}
else {
myAlignment = alignment;
}
myAlignment = alignment;
myIndent = indent;
myWrap = wrap;
@@ -131,9 +120,6 @@ public class GroovyBlock implements Block, GroovyElementTypes, ASTBlock {
@NotNull
public List<Block> getSubBlocks() {
if (mySubBlocks == null) {
mySubBlocks = new GroovyBlockGenerator(this).generateSubBlocks();
}
return mySubBlocks;
}
@@ -205,9 +191,9 @@ public class GroovyBlock implements Block, GroovyElementTypes, ASTBlock {
if (BLOCK_SET.contains(astNode.getElementType()) ||
SWITCH_STATEMENT.equals(astNode.getElementType())) {
// PsiElement psi = ((GroovyBlock)getSubBlocks().get(newChildIndex)).getNode().getPsi();
// if (GeeseUtil.isClosureRBrace(psi)) {
// return new ChildAttributes(Indent.getNoneIndent(), GeeseUtil.calculateRBraceAlignment(psi, myInnerAlignments));
// }
// if (GeeseUtil.isClosureRBrace(psi)) {
// return new ChildAttributes(Indent.getNoneIndent(), GeeseUtil.calculateRBraceAlignment(psi, myInnerAlignments));
// }
return new ChildAttributes(Indent.getNormalIndent(), null);
}
@@ -242,6 +228,10 @@ public 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
@@ -250,8 +240,8 @@ public class GroovyBlock implements Block, GroovyElementTypes, ASTBlock {
if (node.getElementType() instanceof ILazyParseableElementType) return false;
ASTNode lastChild = node.getLastChildNode();
while (lastChild != null &&
!(lastChild.getElementType() instanceof ILazyParseableElementType) &&
(lastChild.getPsi() instanceof PsiWhiteSpace || lastChild.getPsi() instanceof PsiComment)) {
!(lastChild.getElementType() instanceof ILazyParseableElementType) &&
(lastChild.getPsi() instanceof PsiWhiteSpace || lastChild.getPsi() instanceof PsiComment)) {
lastChild = lastChild.getTreePrev();
}
return lastChild != null && (lastChild.getPsi() instanceof PsiErrorElement || isIncomplete(lastChild));
@@ -82,16 +82,18 @@ 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) {
this.myBlock = block;
myBlock = block;
myNode = myBlock.getNode();
myAlignment = myBlock.getAlignment();
myWrap = myBlock.getWrap();
mySettings = myBlock.getSettings();
myInnerAlignments = myBlock.getInnerAlignments();
myGroovySettings = myBlock.getGroovySettings();
myBlocks = myBlock.myBlocks;
}
@@ -134,7 +136,8 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
for (ASTNode childNode : children) {
if (childNode.getTextRange().getLength() > 0) {
final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
subBlocks.add(new GroovyBlock(childNode, myAlignment, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
subBlocks.add(new GroovySimpleBlock(childNode, myAlignment, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks));
}
}
return subBlocks;
@@ -155,8 +158,8 @@ 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 GroovyBlock(childNode, isKeyword(childNode) ? null : newAlignment, indent, myWrap, mySettings, myGroovySettings,
myInnerAlignments));
subBlocks.add(new GroovySimpleBlock(childNode, isKeyword(childNode) ? null : newAlignment, indent, myWrap, mySettings, myGroovySettings,
myInnerAlignments, myBlocks));
}
return subBlocks;
}
@@ -169,7 +172,8 @@ 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 GroovyBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
subBlocks.add(new GroovySimpleBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks));
}
return subBlocks;
}
@@ -178,8 +182,8 @@ 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 GroovyBlock(childNode, myInnerAlignments.get(childNode.getPsi()), indent, myWrap, mySettings, myGroovySettings,
myInnerAlignments));
subBlocks.add(new GroovySimpleBlock(childNode, myInnerAlignments.get(childNode.getPsi()), indent, myWrap, mySettings, myGroovySettings,
myInnerAlignments, myBlocks));
}
return subBlocks;
}
@@ -229,7 +233,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
}
}
else if (GeeseUtil.isClosureRBrace(psi) && myGroovySettings.USE_FLYING_GEESE_BRACES) {
myInnerAlignments.put(psi, GeeseUtil.calculateRBraceAlignment(psi, myInnerAlignments));
myInnerAlignments.put(psi, GeeseUtil.calculateRBraceAlignment(psi, myInnerAlignments, myBlocks));
}
else {
if (psi instanceof PsiComment) {
@@ -321,19 +325,22 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
final int start = myNode.getTextRange().getStartOffset();
final int end = myNode.getTextRange().getEndOffset();
subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
subBlocks.add(new GroovySimpleBlock(myNode, myAlignment, Indent.getNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks) {
@NotNull
public TextRange getTextRange() {
return new TextRange(start, start + 3);
}
});
subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
subBlocks.add(new GroovySimpleBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks) {
@NotNull
public TextRange getTextRange() {
return new TextRange(start + 3, end - 3);
}
});
subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
subBlocks.add(new GroovySimpleBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks) {
@NotNull
public TextRange getTextRange() {
return new TextRange(end - 3, end);
@@ -347,13 +354,15 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
final int start = myNode.getTextRange().getStartOffset();
final int end = myNode.getTextRange().getEndOffset();
subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
subBlocks.add(new GroovySimpleBlock(myNode, myAlignment, Indent.getNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks) {
@NotNull
public TextRange getTextRange() {
return new TextRange(start, start + 3);
}
});
subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
subBlocks.add(new GroovySimpleBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks) {
@NotNull
public TextRange getTextRange() {
return new TextRange(start + 3, end);
@@ -435,7 +444,8 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
PsiElement psi = childNode.getPsi();
if (!(psi instanceof GrBinaryExpression)) {
Alignment alignmentToUse = op == psi ? myInnerAlignments.get(op) : alignment;
list.add(new GroovyBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
list.add(new GroovySimpleBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments,
myBlocks));
}
}
if (myExpr.getRightOperand() instanceof GrBinaryExpression) {
@@ -465,7 +475,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));
myInnerAlignments, myBlocks));
}
return;
}
@@ -486,7 +496,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
else {
Alignment alignmentToUse = myInnerAlignments.get(fst.getPsi());
Indent indent = Indent.getContinuationWithoutFirstIndent();
list.add(new GroovyBlock(fst, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
list.add(new GroovySimpleBlock(fst, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments, myBlocks));
}
addNestedChildrenSuffix(list, alignment, topLevel, children, limit);
}
@@ -500,7 +510,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
Indent.getContinuationWithoutFirstIndent() :
Indent.getNoneIndent();
Alignment alignmentToUse = TokenSets.DOTS.contains(type) ? alignment : myInnerAlignments.get(childNode.getPsi());
list.add(new GroovyBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
list.add(new GroovySimpleBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments, myBlocks));
}
}
}
@@ -16,10 +16,7 @@
package org.jetbrains.plugins.groovy.formatter;
import com.intellij.formatting.Block;
import com.intellij.formatting.FormattingModel;
import com.intellij.formatting.FormattingModelBuilder;
import com.intellij.formatting.Indent;
import com.intellij.formatting.*;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
@@ -32,6 +29,7 @@ import com.intellij.psi.formatter.FormattingDocumentModelImpl;
import com.intellij.psi.formatter.PsiBasedFormattingModel;
import com.intellij.psi.impl.source.tree.TreeUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.containers.CollectionFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
@@ -52,7 +50,9 @@ 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 GroovyBlock(astNode, null, Indent.getAbsoluteNoneIndent(), null, groovySettings, customSettings);
final GroovyBlock block = new GroovySimpleBlock(astNode, null, Indent.getAbsoluteNoneIndent(), null, groovySettings, customSettings,
CollectionFactory.<PsiElement, Alignment>hashMap(),
CollectionFactory.<PsiElement, GroovyBlock>hashMap());
return new GroovyFormattingModel(containingFile, block, FormattingDocumentModelImpl.createOn(containingFile));
}
@@ -0,0 +1,43 @@
/*
* 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,42 +33,32 @@ import java.util.Map;
* @author peter
*/
public class MethodCallWithoutQualifierBlock extends GroovyBlock {
private final PsiElement myNameElement;
private final boolean myTopLevel;
private final List<ASTNode> myChildren;
private final PsiElement myElem;
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;
}
private final TextRange myRange;
@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;
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());
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 TextRange getTextRange() {
return new TextRange(myNameElement.getTextRange().getStartOffset(), myElem.getTextRange().getEndOffset());
return myRange;
}
@Override
@@ -273,6 +273,21 @@ def c = { a ->
} }
'''
}
void testGeese3() {
myTempSettings.getCustomSettings(GroovyCodeStyleSettings).USE_FLYING_GEESE_BRACES = true
doTest '''\
foo {
[1].bar {<caret>}
}
''', '''\
foo {
[1].bar {
<caret>
} }
'''
}
}