Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add alignWithFirstAttr option to xml.format.splitAttributes #1560

Merged
merged 1 commit into from
Jul 26, 2023
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 @@ -22,6 +22,7 @@
import org.eclipse.lemminx.services.format.XMLFormatterDocument;
import org.eclipse.lemminx.services.format.XMLFormattingConstraints;
import org.eclipse.lemminx.settings.XMLFormattingOptions;
import org.eclipse.lemminx.settings.XMLFormattingOptions.SplitAttributes;
import org.eclipse.lemminx.utils.StringUtils;
import org.eclipse.lemminx.utils.XMLBuilder;
import org.eclipse.lsp4j.TextEdit;
Expand Down Expand Up @@ -188,9 +189,14 @@ public boolean formatAttributeValue(DOMAttr attr, XMLFormatterDocument formatter
int indentSpaceOffset;
int startOfLineOffset = formatterDocument.getLineAtOffset(attr.getOwnerElement().getStart());

if (formattingOptions.isSplitAttributes()) {
indentSpaceOffset = (attrValueStart + 1) - attr.getNodeAttrName().getStart()
+ formattingOptions.getSplitAttributesIndentSize() * tabSize;
if (formattingOptions.getSplitAttributes() != SplitAttributes.preserve) {
if (formattingOptions.getSplitAttributes() == SplitAttributes.splitNewLine) {
indentSpaceOffset = (attrValueStart + 1) - attr.getNodeAttrName().getStart()
+ formattingOptions.getSplitAttributesIndentSize() * tabSize;
} else {
indentSpaceOffset = (attrValueStart + 1) - attr.getNodeAttrName().getStart()
+ attr.getOwnerElement().getTagName().length() + 2;
}
} else if (formattingOptions.isPreserveAttributeLineBreaks()) {
indentSpaceOffset = attrValueStart - formatterDocument.getOffsetWithPreserveLineBreaks(startOfLineOffset,
attrValueStart, tabSize, formattingOptions.isInsertSpaces());
Expand All @@ -212,7 +218,7 @@ public boolean formatAttributeValue(DOMAttr attr, XMLFormatterDocument formatter
availableLineWidth -= i - lastAttrValueTermIndex;
lastAttrValueTermIndex = i;
if (availableLineWidth < 0 && formatterDocument.isMaxLineWidthSupported()
&& !formattingOptions.isSplitAttributes()) {
&& formattingOptions.getSplitAttributes() == SplitAttributes.preserve) {
indentSpaceOffset = (attrValueStart + 1) - attr.getNodeAttrName().getStart()
+ (parentConstraints.getIndentLevel() + 1) * tabSize;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import java.util.List;

import org.eclipse.lemminx.dom.DOMAttr;
import org.eclipse.lemminx.dom.DOMElement;
import org.eclipse.lemminx.settings.EnforceQuoteStyle;
import org.eclipse.lemminx.settings.XMLFormattingOptions.SplitAttributes;
import org.eclipse.lemminx.utils.StringUtils;
import org.eclipse.lsp4j.TextEdit;

Expand All @@ -33,6 +35,7 @@ public DOMAttributeFormatter(XMLFormatterDocument formatterDocument) {
}

public void formatAttribute(DOMAttr attr, int prevOffset, boolean singleAttribute, boolean useSettings,
boolean isFirstAttr,
XMLFormattingConstraints parentConstraints, List<TextEdit> edits) {
int indentLevel = parentConstraints.getIndentLevel();
// 1) format before attribute name : indent left of the attribute name
Expand All @@ -44,10 +47,14 @@ public void formatAttribute(DOMAttr attr, int prevOffset, boolean singleAttribut
if (isPreserveAttributeLineBreaks() && hasLineBreak(prevOffset, attr.getStart())) {
replaceLeftSpacesWithIndentation(indentLevel + 1, prevOffset, attr.getStart(), true, edits);
alreadyIndented = true;
} else if (isSplitAttributes() && !singleAttribute) {
} else if (getSplitAttributes() == SplitAttributes.splitNewLine && !singleAttribute) {
replaceLeftSpacesWithIndentation(indentLevel + getSplitAttributesIndentSize(), prevOffset,
attr.getStart(), true, edits);
alreadyIndented = true;
} else if (getSplitAttributes() == SplitAttributes.alignWithFirstAttr && !isFirstAttr) {
replaceLeftSpacesWithIndentationWithOffsetSpaces(getFirstAttrOffset(attr.getOwnerElement(), indentLevel), prevOffset,
attr.getStart(), edits);
alreadyIndented = true;
}
}

Expand All @@ -74,7 +81,7 @@ public void formatAttribute(DOMAttr attr, int prevOffset, boolean singleAttribut
int availableLineWidth = parentConstraints.getAvailableLineWidth();
if (isPreserveAttributeLineBreaks() && hasLineBreak(prevOffset, attr.getStart())) {
availableLineWidth = getMaxLineWidth() - getTabSize() * (indentLevel + 1);
} else if (isSplitAttributes() && !singleAttribute) {
} else if (getSplitAttributes() == SplitAttributes.splitNewLine && !singleAttribute) {
availableLineWidth = getMaxLineWidth()
- getTabSize() * (indentLevel + getSplitAttributesIndentSize());
} else {
Expand All @@ -93,7 +100,7 @@ public void formatAttribute(DOMAttr attr, int prevOffset, boolean singleAttribut
int from = prevOffset;
int to = attr.getStart();
if (isMaxLineWidthSupported() && parentConstraints.getAvailableLineWidth() < 0
&& !isSplitAttributes()) {
&& getSplitAttributes() == SplitAttributes.preserve) {
replaceLeftSpacesWithIndentation(indentLevel + 1, from, to, true, edits);
int attrValuelength = attr.getValue() != null ? attr.getValue().length() : 0;
parentConstraints.setAvailableLineWidth(
Expand Down Expand Up @@ -129,6 +136,13 @@ public void formatAttribute(DOMAttr attr, int prevOffset, boolean singleAttribut
}
}

private int getFirstAttrOffset(DOMElement ownerElement, int indentLevel) {
return getTabSize() * indentLevel + ownerElement.getTagName().length() + 2 /*
* +1 for '<', +1 for space between
* element name and first attr name
*/;
}

private void formatAttributeValue(DOMAttr attr, XMLFormattingConstraints parentConstraints, List<TextEdit> edits) {
formatterDocument.formatAttributeValue(attr, parentConstraints, edits);
}
Expand All @@ -137,6 +151,11 @@ private void replaceQuoteWithPreferred(int from, int to, List<TextEdit> edits) {
formatterDocument.replaceQuoteWithPreferred(from, to, edits);
}

private void replaceLeftSpacesWithIndentationWithOffsetSpaces(int spaceCount, int from, int to,
List<TextEdit> edits) {
formatterDocument.replaceLeftSpacesWithIndentationWithOffsetSpaces(spaceCount, from, to, true, edits);
}

private void replaceLeftSpacesWithOneSpace(int from, int to, List<TextEdit> edits) {
formatterDocument.replaceLeftSpacesWithOneSpace(from, to, edits);
}
Expand All @@ -150,8 +169,8 @@ private void removeLeftSpaces(int from, int to, List<TextEdit> edits) {
formatterDocument.removeLeftSpaces(from, to, edits);
}

private boolean isSplitAttributes() {
return formatterDocument.getSharedSettings().getFormattingSettings().isSplitAttributes();
private SplitAttributes getSplitAttributes() {
return formatterDocument.getSharedSettings().getFormattingSettings().getSplitAttributes();
}

private int getSplitAttributesIndentSize() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.eclipse.lemminx.dom.DOMNode;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.settings.XMLFormattingOptions.EmptyElements;
import org.eclipse.lemminx.settings.XMLFormattingOptions.SplitAttributes;
import org.eclipse.lemminx.utils.StringUtils;
import org.eclipse.lsp4j.TextEdit;

Expand Down Expand Up @@ -214,9 +215,12 @@ private int formatAttributes(DOMElement element, XMLFormattingConstraints parent
// <foo| attr1="" attr2="">.
int prevOffset = element.getOffsetAfterStartTag();
boolean singleAttribute = attributes.size() == 1;
boolean isFirstAttr = true;
for (DOMAttr attr : attributes) {
// Format current attribute
attributeFormatter.formatAttribute(attr, prevOffset, singleAttribute, true, parentConstraints, edits);
attributeFormatter.formatAttribute(attr, prevOffset, singleAttribute, true, isFirstAttr,
parentConstraints, edits);
isFirstAttr = false;
// set the previous offset with end of the current attribute:
// <foo attr1=""| attr2="".
prevOffset = attr.getEnd();
Expand Down Expand Up @@ -267,9 +271,15 @@ && hasLineBreak(getLastAttribute(element).getEnd(), startTagClose)) {
}
} else if (shouldFormatClosingBracketNewLine(element)) {
int indentLevel = parentConstraints.getIndentLevel();
replaceLeftSpacesWithIndentation(indentLevel + getSplitAttributesIndentSize(), startTagOpen, startTagClose,
true, edits);
return (indentLevel + getSplitAttributesIndentSize()) * getTabSize();
if (getSplitAttributes() == SplitAttributes.splitNewLine) {
replaceLeftSpacesWithIndentation(indentLevel + getSplitAttributesIndentSize(), startTagOpen,
startTagClose, true, edits);
return (indentLevel + getSplitAttributesIndentSize()) * getTabSize();
} else { /* splitAttributes == alignWithFirstAttr */
int indentOffset = indentLevel * getTabSize() + element.getTagName().length() + 2;
replaceLeftSpacesWithIndentationWithOffsetSpaces(indentOffset, startTagOpen, startTagClose, edits);
return indentOffset;
}
}
if (element.isSelfClosed()) {
if (spaceBeforeEmptyCloseTag) {
Expand Down Expand Up @@ -380,7 +390,7 @@ private boolean shouldFormatClosingBracketNewLine(DOMElement element) {
boolean isSingleAttribute = element.getAttributeNodes() != null ? element.getAttributeNodes().size() == 1
: true;
return (formatterDocument.getSharedSettings().getFormattingSettings().getClosingBracketNewLine()
&& isSplitAttributes() && !isSingleAttribute);
&& getSplitAttributes() != SplitAttributes.preserve && !isSingleAttribute);
}

private void replaceLeftSpacesWith(int from, int to, String replace, List<TextEdit> edits) {
Expand All @@ -398,6 +408,11 @@ private void replaceLeftSpacesWithIndentationPreservedNewLines(int spaceStart, i
edits);
}

private void replaceLeftSpacesWithIndentationWithOffsetSpaces(int spaceCount, int from, int to,
List<TextEdit> edits) {
formatterDocument.replaceLeftSpacesWithIndentationWithOffsetSpaces(spaceCount, from, to, true, edits);
}

private void removeLeftSpaces(int from, int to, List<TextEdit> edits) {
formatterDocument.removeLeftSpaces(from, to, edits);
}
Expand Down Expand Up @@ -439,8 +454,8 @@ private boolean isPreserveAttributeLineBreaks() {
return formatterDocument.getSharedSettings().getFormattingSettings().isPreserveAttributeLineBreaks();
}

private boolean isSplitAttributes() {
return formatterDocument.getSharedSettings().getFormattingSettings().isSplitAttributes();
private SplitAttributes getSplitAttributes() {
return formatterDocument.getSharedSettings().getFormattingSettings().getSplitAttributes();
}

private int getSplitAttributesIndentSize() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void formatProcessingInstruction(DOMProcessingInstruction processingInstr
List<DOMAttr> attributes = processingInstruction.getAttributeNodes();
boolean singleAttribute = attributes.size() == 1;
for (DOMAttr attr : attributes) {
attributeFormatter.formatAttribute(attr, prevOffset, singleAttribute, false, parentConstraints, edits);
attributeFormatter.formatAttribute(attr, prevOffset, singleAttribute, false, false, parentConstraints, edits);
prevOffset = attr.getEnd();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.eclipse.lemminx.services.extensions.format.IFormatterParticipant;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.settings.XMLFormattingOptions.EmptyElements;
import org.eclipse.lemminx.settings.XMLFormattingOptions.SplitAttributes;
import org.eclipse.lemminx.utils.XMLBuilder;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
Expand Down Expand Up @@ -554,7 +555,7 @@ private void formatAttributes(DOMElement element) throws BadLocationException {
prevOffset = attr.getEnd();
}
if ((this.sharedSettings.getFormattingSettings().getClosingBracketNewLine()
&& this.sharedSettings.getFormattingSettings().isSplitAttributes()) && !isSingleAttribute) {
&& this.sharedSettings.getFormattingSettings().getSplitAttributes() == SplitAttributes.splitNewLine) && !isSingleAttribute) {
xmlBuilder.linefeed();
// Indent by tag + splitAttributesIndentSize to match with attribute indent
// level
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ public class XMLFormattingOptions extends org.eclipse.lemminx.settings.LSPFormat
private boolean legacy;
private int maxLineWidth;

private boolean splitAttributes;
public static enum SplitAttributes {
preserve, splitNewLine, alignWithFirstAttr;
}

private String splitAttributes;
private boolean joinCDATALines;
private boolean formatComments;
private boolean joinCommentLines;
Expand Down Expand Up @@ -150,7 +154,7 @@ private void initializeDefaultSettings() {
super.setTabSize(DEFAULT_TAB_SIZE);
super.setInsertSpaces(true);
super.setTrimFinalNewlines(true);
this.setSplitAttributes(false);
this.setSplitAttributes(SplitAttributes.preserve);
this.setJoinCDATALines(false);
this.setFormatComments(true);
this.setJoinCommentLines(false);
Expand Down Expand Up @@ -193,12 +197,19 @@ public XMLFormattingOptions(FormattingOptions options) {
this(options, true);
}

public boolean isSplitAttributes() {
return splitAttributes;
public SplitAttributes getSplitAttributes() {
String value = splitAttributes;
if ((value != null)) {
try {
return SplitAttributes.valueOf(value);
} catch (Exception e) {
}
}
return SplitAttributes.preserve;
}

public void setSplitAttributes(final boolean splitAttributes) {
this.splitAttributes = splitAttributes;
public void setSplitAttributes(SplitAttributes splitAttributes) {
this.splitAttributes = splitAttributes.name();
}

public boolean isJoinCDATALines() {
Expand Down Expand Up @@ -347,7 +358,7 @@ public void setPreserveAttributeLineBreaks(final boolean preserveAttributeLineBr
* @return the value of preserveAttrLineBreaks
*/
public boolean isPreserveAttributeLineBreaks() {
if (this.isSplitAttributes()) {
if (this.getSplitAttributes() != SplitAttributes.preserve) {
// splitAttributes overrides preserveAttrLineBreaks
return false;
}
Expand Down Expand Up @@ -438,7 +449,7 @@ public XMLFormattingOptions merge(XMLFormattingOptions formattingOptions) {
setTrimTrailingWhitespace(formattingOptions.isTrimTrailingWhitespace());
setLegacy(formattingOptions.isLegacy());
setMaxLineWidth(formattingOptions.getMaxLineWidth());
setSplitAttributes(formattingOptions.isSplitAttributes());
setSplitAttributes(formattingOptions.getSplitAttributes());
setJoinCDATALines(formattingOptions.isJoinCDATALines());
setFormatComments(formattingOptions.isFormatComments());
setJoinCommentLines(formattingOptions.isJoinCommentLines());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.eclipse.lemminx.services.extensions.format.IFormatterParticipant;
import org.eclipse.lemminx.settings.EnforceQuoteStyle;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.settings.XMLFormattingOptions.SplitAttributes;

/**
* XML content builder utilities.
Expand Down Expand Up @@ -171,7 +172,7 @@ public XMLBuilder addPrologAttribute(DOMAttr attr) {
* @return
*/
public XMLBuilder addAttribute(String name, String value, int level, boolean surroundWithQuotes) {
if (isSplitAttributes()) {
if (getSplitAttributes()== SplitAttributes.splitNewLine) {
linefeed();
indent(level + sharedSettings.getFormattingSettings().getSplitAttributesIndentSize());
} else {
Expand All @@ -187,7 +188,7 @@ public XMLBuilder addAttribute(DOMAttr attr, int level) {
}

private XMLBuilder addAttribute(DOMAttr attr, int level, boolean surroundWithQuotes) {
if (isSplitAttributes()) {
if (getSplitAttributes()== SplitAttributes.splitNewLine) {
linefeed();
indent(level + sharedSettings.getFormattingSettings().getSplitAttributesIndentSize());
} else {
Expand Down Expand Up @@ -529,8 +530,8 @@ private boolean isJoinCDATALines() {
return sharedSettings.getFormattingSettings().isJoinCDATALines();
}

private boolean isSplitAttributes() {
return sharedSettings.getFormattingSettings().isSplitAttributes();
private SplitAttributes getSplitAttributes() {
return sharedSettings.getFormattingSettings().getSplitAttributes();
}

private boolean isInsertSpaces() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.eclipse.lemminx.commons.BadLocationException;
import org.eclipse.lemminx.extensions.xsi.settings.XSISchemaLocationSplit;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.settings.XMLFormattingOptions.SplitAttributes;
import org.junit.jupiter.api.Test;

/**
Expand Down Expand Up @@ -180,7 +181,7 @@ private static SharedSettings createSettings() {
SharedSettings settings = new SharedSettings();
settings.getFormattingSettings().setInsertSpaces(true);
settings.getFormattingSettings().setTabSize(2);
settings.getFormattingSettings().setSplitAttributes(true);
settings.getFormattingSettings().setSplitAttributes(SplitAttributes.splitNewLine);
settings.getFormattingSettings().setPreserveEmptyContent(true);
settings.getFormattingSettings().setLegacy(true);
return settings;
Expand Down
Loading