Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -576,14 +576,18 @@ public boolean placeNewLineAfterModifiers() {
return preferences.getBoolean(PLACE_NEW_LINE_AFTER_MODIFIERS, getDefaultAsBoolean(PLACE_NEW_LINE_AFTER_MODIFIERS));
}

public boolean groupMulitlineAssignment() {
public boolean groupMultilineAssignment() {
return preferences.getBoolean(GROUP_ALIGNMENT_ASSIGNMENT, getDefaultAsBoolean(GROUP_ALIGNMENT_ASSIGNMENT));
}

public boolean groupMulitlineArrayInit() {
public boolean groupMultilineArrayInit() {
return preferences.getBoolean(GROUP_ALIGNMENT_ARRAY_INIT, getDefaultAsBoolean(GROUP_ALIGNMENT_ARRAY_INIT));
}

public boolean groupMultilineMatchArmArrow() {
return preferences.getBoolean(GROUP_ALIGNMENT_MATCH_ARM_ARROW, getDefaultAsBoolean(GROUP_ALIGNMENT_MATCH_ARM_ARROW));
}

// Wrapping ----------------------------------------------------------------

public WrapStyle wrapGroupUseList() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ public final class FmtOptions {
public static final String ALIGN_MULTILINE_ARRAY_INIT = "alignMultilineArrayInit"; //NOI18N
public static final String GROUP_ALIGNMENT_ASSIGNMENT = "groupAlignmentAssignment"; //NOI18N
public static final String GROUP_ALIGNMENT_ARRAY_INIT = "groupAlignmentArrayInit"; //NOI18N
public static final String GROUP_ALIGNMENT_MATCH_ARM_ARROW = "groupAlignmentMatchArmArrow"; //NOI18N
public static final String WRAP_GROUP_USE_LIST = "wrapGroupUseList"; //NOI18N
public static final String WRAP_EXTENDS_IMPLEMENTS_KEYWORD = "wrapExtendsImplementsKeyword"; //NOI18N
public static final String WRAP_EXTENDS_IMPLEMENTS_LIST = "wrapExtendsImplementsList"; //NOI18N
Expand Down Expand Up @@ -392,6 +393,7 @@ private static void createDefaults() {
{PLACE_NEW_LINE_AFTER_MODIFIERS, FALSE}, //NOI18N

{GROUP_ALIGNMENT_ARRAY_INIT, FALSE},
{GROUP_ALIGNMENT_MATCH_ARM_ARROW, FALSE},
{GROUP_ALIGNMENT_ASSIGNMENT, FALSE},
{WRAP_GROUP_USE_LIST, WRAP_ALWAYS},
{WRAP_EXTENDS_IMPLEMENTS_KEYWORD, WRAP_NEVER}, //NOI18N
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,12 @@ public void setAnchorColumn(int column) {
*/
public static class AssignmentAnchorToken extends FormatToken {

public enum Type {
ASSIGNMENT, // "="
ARRAY, // "=>"
MATCH_ARM, // "=>"
}

/**
* length of the identifier that is before the aligned operator
*/
Expand All @@ -315,22 +321,28 @@ public static class AssignmentAnchorToken extends FormatToken {
*/
private AssignmentAnchorToken previous;
private final boolean multilined;
private final Type type;

public AssignmentAnchorToken(int offset, boolean multilined) {
this(offset, multilined, Type.ASSIGNMENT);
}

public AssignmentAnchorToken(int offset, boolean multilined, Type type) {
super(Kind.ASSIGNMENT_ANCHOR, offset);
length = -1;
maxLength = -1;
previous = null;
isInGroup = false;
this.multilined = multilined;
this.type = type;
}

public int getLenght() {
public int getLength() {
return length;
}

public void setLenght(int lenght) {
this.length = lenght;
public void setLength(int length) {
this.length = length;
}

public int getMaxLength() {
Expand Down Expand Up @@ -361,6 +373,9 @@ public boolean isMultilined() {
return multilined;
}

public Type getType() {
return type;
}
}

public static class UnbreakableSequenceToken extends FormatToken {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.netbeans.editor.BaseDocument;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.csl.spi.GsfUtilities;
import org.netbeans.modules.php.editor.CodeUtils;
import org.netbeans.modules.php.editor.indent.FormatToken.AssignmentAnchorToken;
import org.netbeans.modules.php.editor.indent.TokenFormatter.DocumentOptions;
import org.netbeans.modules.php.editor.lexer.LexUtilities;
Expand Down Expand Up @@ -419,7 +420,7 @@ public void visit(ArrayElement node) {
scan(node.getKey());
while (ts.moveNext() && ts.offset() < node.getValue().getStartOffset()) {
if (isKeyValueOperator(ts.token())) {
handleGroupAlignment(node.getKey(), multilinedArray);
handleGroupAlignment(node.getKey(), multilinedArray, AssignmentAnchorToken.Type.ARRAY);
}
addFormatToken(formatTokens);
}
Expand Down Expand Up @@ -2245,6 +2246,7 @@ public void visit(MatchExpression node) {
scan(node.getExpression());

addWhitespaceBeforeMatchLeftBraceToken(node);
createGroupAlignment();
List<MatchArm> matchArms = node.getMatchArms();
if (!matchArms.isEmpty()) {
MatchArm first = matchArms.get(0);
Expand All @@ -2259,6 +2261,8 @@ public void visit(MatchExpression node) {
if (disabled) {
enableIndentForFunctionInvocation(node.getEndOffset());
}
addAllUntilOffset(node.getEndOffset());
resetGroupAlignment();
}

private void addWhitespaceBeforeMatchRightBraceToken(MatchExpression node) {
Expand Down Expand Up @@ -2289,6 +2293,53 @@ private void addWhitespaceBeforeMatchLeftBraceToken(MatchExpression node) {
}
}

private boolean isMultilinedMatchArm(MatchExpression matchExpression, MatchArm matchArm) {
boolean result = false;
List<MatchArm> matchArms = matchExpression.getMatchArms();
int start = matchExpression.getStartOffset();
for (MatchArm arm : matchArms) {
if (arm.getStartOffset() == matchArm.getStartOffset()) {
int end = arm.getStartOffset();
try {
result = document.getText(start, end - start).contains(CodeUtils.NEW_LINE);
} catch (BadLocationException ex) {
LOGGER.log(Level.WARNING, "Invalid offset: {0}", ex.offsetRequested()); // NOI18N
}
}
start = arm.getEndOffset();
}
return result;
}

@Override
public void visit(MatchArm node) {
scan(node.getConditions());
MatchExpression parentMatchExpression = getParentMatchExpression();
boolean isMultilined = isMultilinedMatchArm(parentMatchExpression, node);
while (ts.moveNext() && ts.offset() < node.getExpression().getStartOffset()) {
if (isKeyValueOperator(ts.token())) {
List<Expression> conditions = node.getConditions();
handleGroupAlignment(conditions, isMultilined, AssignmentAnchorToken.Type.MATCH_ARM);
}
addFormatToken(formatTokens);
}
ts.movePrevious();
scan(node.getExpression());
}

@CheckForNull
private MatchExpression getParentMatchExpression() {
MatchExpression result = null;
for (int i = 0; i < path.size(); i++) {
ASTNode parentInPath = path.get(i);
if (parentInPath instanceof MatchExpression) {
result = (MatchExpression) parentInPath;
break;
}
}
return result;
}

@Override
public void visit(TryStatement node) {
scan(node.getBody());
Expand Down Expand Up @@ -3284,26 +3335,49 @@ private boolean moveNext() {
* the group
*/
private void handleGroupAlignment(int nodeLength, boolean multilined) {
handleGroupAlignment(nodeLength, multilined, AssignmentAnchorToken.Type.ASSIGNMENT);
}

/**
* Handle group alignment.
*
* @param nodeLength the node length
* @param multilined {@code true} if it has a new line, otherwise {@code false}
* @param type the assingment type
*/
private void handleGroupAlignment(int nodeLength, boolean multilined, AssignmentAnchorToken.Type type) {
if (groupAlignmentTokenHolders.isEmpty()) {
createGroupAlignment();
}
GroupAlignmentTokenHolder tokenHolder = groupAlignmentTokenHolders.peek();
FormatToken.AssignmentAnchorToken previousGroupToken = tokenHolder.getToken();
AssignmentAnchorToken previousGroupToken = tokenHolder.getToken();
if (previousGroupToken == null) {
// it's the first line in the group
previousGroupToken = new FormatToken.AssignmentAnchorToken(ts.offset(), multilined);
previousGroupToken.setLenght(nodeLength);
previousGroupToken = new AssignmentAnchorToken(ts.offset(), multilined, type);
previousGroupToken.setLength(nodeLength);
previousGroupToken.setMaxLength(nodeLength);
} else {
// it's a next line in the group.
FormatToken.AssignmentAnchorToken aaToken = new FormatToken.AssignmentAnchorToken(ts.offset(), multilined);
aaToken.setLenght(nodeLength);
AssignmentAnchorToken aaToken = new AssignmentAnchorToken(ts.offset(), multilined, type);
aaToken.setLength(nodeLength);
aaToken.setPrevious(previousGroupToken);
aaToken.setIsInGroup(true);
if (!previousGroupToken.isInGroup()) {
previousGroupToken.setIsInGroup(true);
}
if (previousGroupToken.getMaxLength() < nodeLength) {
if (type == AssignmentAnchorToken.Type.MATCH_ARM) {
int maxLength = getValidMaxLength(aaToken);
previousGroupToken = aaToken;
do {
aaToken.setMaxLength(maxLength);
AssignmentAnchorToken previousToken = aaToken.getPrevious();
if (previousToken != null
&& previousToken.getMaxLength() == maxLength) {
break;
}
aaToken = previousToken;
} while (aaToken != null);
} else if (previousGroupToken.getMaxLength() < nodeLength) {
// if the length of the current identifier is bigger, then is in
// the group so far, change max length for all items in the group
previousGroupToken = aaToken;
Expand All @@ -3320,6 +3394,25 @@ private void handleGroupAlignment(int nodeLength, boolean multilined) {
formatTokens.add(previousGroupToken);
}

private int getValidMaxLength(FormatToken.AssignmentAnchorToken assignmentAnchorToken) {
// e.g. avoid adding extra spaces after "1" and "2" in the following case
// match ($type) {
// "1" => 1, "maxLength" => "maxLength", "2" => 2,
// }
int maxLength = assignmentAnchorToken.getLength();
AssignmentAnchorToken aaToken = assignmentAnchorToken;
int multilinedMaxLength = -1;
do {
int length = aaToken.getLength();
maxLength = Integer.max(maxLength, length);
if (aaToken.isMultilined()) {
multilinedMaxLength = Integer.max(multilinedMaxLength, length);
}
aaToken = aaToken.getPrevious();
} while (aaToken != null);
return multilinedMaxLength != -1 ? multilinedMaxLength : maxLength;
}

private void handleGroupAlignment(int nodeLength) {
handleGroupAlignment(nodeLength, false);
}
Expand All @@ -3328,8 +3421,14 @@ private void handleGroupAlignment(ASTNode node) {
handleGroupAlignment(node.getEndOffset() - node.getStartOffset(), false);
}

private void handleGroupAlignment(ASTNode node, boolean multilined) {
handleGroupAlignment(node.getEndOffset() - node.getStartOffset(), multilined);
private void handleGroupAlignment(ASTNode node, boolean multilined, AssignmentAnchorToken.Type type) {
handleGroupAlignment(node.getEndOffset() - node.getStartOffset(), multilined, type);
}

private void handleGroupAlignment(List<? extends ASTNode> nodes, boolean multilined, AssignmentAnchorToken.Type type) {
int start = nodes.get(0).getStartOffset();
int end = nodes.get(nodes.size() - 1).getEndOffset();
handleGroupAlignment(end - start, multilined, type);
}

private void resetAndCreateGroupAlignment() {
Expand Down
Loading