Skip to content

Commit

Permalink
Improve text formatting for experimental formatter
Browse files Browse the repository at this point in the history
Signed-off-by: Jessica He <[email protected]>
  • Loading branch information
JessicaJHee authored and angelozerr committed Oct 27, 2022
1 parent 2594803 commit 719bf9d
Show file tree
Hide file tree
Showing 15 changed files with 567 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ public void formatElement(DOMElement element, XMLFormattingConstraints parentCon
int indentLevel = parentConstraints.getIndentLevel();
int nb = formatStartTagElement(element, parentConstraints, emptyElements, start, end, edits);

// Set indent level for text in mixed content
int mixedIndentLevel = parentConstraints.getMixedContentIndentLevel();
if (mixedIndentLevel == 0 && parentConstraints.getFormatElementCategory() == FormatElementCategory.MixedContent){
parentConstraints.setMixedContentIndentLevel(indentLevel);
}

if (emptyElements == EmptyElements.ignore) {
// Format children of the element
XMLFormattingConstraints constraints = new XMLFormattingConstraints();
Expand All @@ -54,14 +60,14 @@ public void formatElement(DOMElement element, XMLFormattingConstraints parentCon
constraints.setIndentLevel(indentLevel + 1);
}
constraints.setFormatElementCategory(getFormatElementCategory(element, parentConstraints));
constraints.setAvailableLineWidth(getMaxLineWidth() - nb);

formatChildren(element, constraints, start, end, edits);

// Format end tag element with proper indentation
if (element.hasEndTag()) {
formatEndTagElement(element, parentConstraints, constraints, edits);
nb = formatEndTagElement(element, parentConstraints, constraints, edits);
}
parentConstraints.setAvailableLineWidth(constraints.getAvailableLineWidth() - nb);
}
}

Expand Down Expand Up @@ -101,6 +107,7 @@ private int formatStartTagElement(DOMElement element, XMLFormattingConstraints p
width -= formatterDocument.getLineDelimiter().length();
}
}
width = element.getTagName() != null ? element.getTagName().length() + 1 : 0;
break;
case IgnoreSpace:
// If preserve new lines
Expand All @@ -123,15 +130,18 @@ private int formatStartTagElement(DOMElement element, XMLFormattingConstraints p
width -= formatterDocument.getLineDelimiter().length();
}
}
parentConstraints.setAvailableLineWidth(getMaxLineWidth());
break;
case NormalizeSpace:
width++;
width = element.getTagName() != null ? element.getTagName().length() + 1 : 0;
break;
}
parentConstraints.setAvailableLineWidth(parentConstraints.getAvailableLineWidth() - width);
if (formatElementCategory != FormatElementCategory.PreserveSpace) {
formatAttributes(element, parentConstraints, edits);

boolean formatted = false;
width = 0;
switch (emptyElements) {
case expand: {
if (element.isSelfClosed()) {
Expand Down Expand Up @@ -185,6 +195,7 @@ private int formatStartTagElement(DOMElement element, XMLFormattingConstraints p
break;
}
default:
width++;
}

if (!formatted) {
Expand All @@ -193,6 +204,7 @@ private int formatStartTagElement(DOMElement element, XMLFormattingConstraints p
}
}
}
parentConstraints.setAvailableLineWidth(parentConstraints.getAvailableLineWidth() - width);
return width;
}

Expand Down Expand Up @@ -289,6 +301,9 @@ private int formatEndTagElement(DOMElement element, XMLFormattingConstraints par
int endTagOffset = element.getEndTagOpenOffset();
int startTagCloseOffset = element.getStartTagCloseOffset();

int width = 0;
int nbSpaces = 0;

switch (formatElementCategory) {
case PreserveSpace:
// Preserve existing spaces
Expand All @@ -300,9 +315,10 @@ private int formatEndTagElement(DOMElement element, XMLFormattingConstraints par
if ((element.getLastChild().isElement() || element.getLastChild().isComment())
&& Character.isWhitespace(formatterDocument.getText().charAt(endTagOffset - 1))
&& !isPreserveEmptyContent()) {
replaceLeftSpacesWithIndentation(indentLevel, startTagCloseOffset, endTagOffset, true,
nbSpaces = replaceLeftSpacesWithIndentation(indentLevel, startTagCloseOffset, endTagOffset, true,
edits);
}
width = element.getTagName() != null ? nbSpaces + element.getTagName().length() + 2 : nbSpaces;
break;
case IgnoreSpace:
// If preserve new lines
Expand All @@ -316,9 +332,12 @@ private int formatEndTagElement(DOMElement element, XMLFormattingConstraints par
int newLineCount = currentNewLineCount == 0 ? 1 : currentNewLineCount;
replaceLeftSpacesWithIndentationWithMultiNewLines(indentLevel, startTagCloseOffset, endTagOffset,
newLineCount, edits);
nbSpaces = indentLevel * getTabSize();
width = element.getTagName() != null ? nbSpaces + element.getTagName().length() + 2 : nbSpaces;
break;
}
case NormalizeSpace:
width = element.getTagName() != null ? element.getTagName().length() + 2 : 0;
break;
}
// 2) remove some spaces between the end tag and and close bracket
Expand All @@ -327,8 +346,9 @@ private int formatEndTagElement(DOMElement element, XMLFormattingConstraints par
if (element.isEndTagClosed()) {
int endTagCloseOffset = element.getEndTagCloseOffset();
removeLeftSpaces(element.getEndTagOpenOffset(), endTagCloseOffset, edits);
width++;
}
return 0;
return width;
}

/**
Expand Down Expand Up @@ -476,4 +496,8 @@ private boolean shouldCollapseEmptyElement(DOMElement element, SharedSettings se
private int getMaxLineWidth() {
return formatterDocument.getMaxLineWidth();
}

private int getTabSize() {
return formatterDocument.getSharedSettings().getFormattingSettings().getTabSize();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import java.util.List;

import org.eclipse.lemminx.dom.DOMElement;
import org.eclipse.lemminx.dom.DOMText;
import org.eclipse.lsp4j.TextEdit;

Expand All @@ -38,6 +39,8 @@ public void formatText(DOMText textNode, XMLFormattingConstraints parentConstrai
FormatElementCategory formatElementCategory = parentConstraints.getFormatElementCategory();
String text = formatterDocument.getText();
int availableLineWidth = parentConstraints.getAvailableLineWidth();
int indentLevel = parentConstraints.getIndentLevel();
int maxLineWidth = getMaxLineWidth();

int spaceStart = -1;
int spaceEnd = -1;
Expand All @@ -62,23 +65,37 @@ public void formatText(DOMText textNode, XMLFormattingConstraints parentConstrai
while (i + 1 < textNode.getEnd() && !Character.isWhitespace(text.charAt(i + 1))) {
i++;
}
int contentEnd = i;
availableLineWidth -= (contentEnd + 1 - contentStart);

if (formatElementCategory != FormatElementCategory.PreserveSpace
&& formatElementCategory != FormatElementCategory.IgnoreSpace) {
int contentEnd = i + 1;
availableLineWidth -= contentEnd - contentStart;
if (formatElementCategory != FormatElementCategory.PreserveSpace) {
if (textNode.getStart() != contentStart && availableLineWidth >= 0
&& (isJoinContentLines() || !containsNewLine)) {
// Decrement width for normalized space between text content (not done at
// beginning)
availableLineWidth--;
}
if (availableLineWidth < 0) {
int mixedContentIndentLevel = parentConstraints.getMixedContentIndentLevel() == 0 ? indentLevel
: parentConstraints.getMixedContentIndentLevel();
if (spaceStart != -1) {
insertLineBreak(spaceStart, contentStart, edits);
availableLineWidth = getMaxLineWidth() - (contentEnd - contentStart + 1);
replaceLeftSpacesWithIndentation(mixedContentIndentLevel, spaceStart, contentStart,
true, edits);
availableLineWidth = maxLineWidth - (contentEnd - contentStart)
- mixedContentIndentLevel * getTabSize();
containsNewLine = false;
}
} else if (isJoinContentLines() || (spaceStart == textNode.getStart() || !containsNewLine)) {
} else if (isJoinContentLines() || !containsNewLine) {
// Case of isJoinContent == true: join all text content with single space
// Case of isJoinContent == false: normalize space only between element start
// tag and start of text content or doesn't contain a new line
replaceSpacesWithOneSpace(spaceStart, spaceEnd-1, edits);
replaceSpacesWithOneSpace(spaceStart, spaceEnd - 1, edits);
containsNewLine = false;
availableLineWidth --;
} else if (containsNewLine) {
replaceLeftSpacesWithIndentationPreservedNewLines(contentStart, spaceStart, spaceEnd,
indentLevel, edits);
containsNewLine = false;
availableLineWidth = maxLineWidth - (contentEnd - contentStart)
- indentLevel * getTabSize();
} else {
availableLineWidth -= spaceEnd - spaceStart;
}
Expand All @@ -89,8 +106,42 @@ public void formatText(DOMText textNode, XMLFormattingConstraints parentConstrai
}
}
if (formatElementCategory != FormatElementCategory.PreserveSpace
&& formatElementCategory != FormatElementCategory.IgnoreSpace) {
replaceSpacesWithOneSpace(spaceStart, spaceEnd, edits);
&& formatElementCategory != FormatElementCategory.IgnoreSpace && spaceEnd + 1 != text.length()) {
DOMElement parentElement = textNode.getParentElement();
// Don't format final spaces if text is at the end of the file
if (!containsNewLine || isJoinContentLines()) {
// Replace spaces with single space in the case of:
// 1. there is no new line
// 2. isJoinContentLines
replaceSpacesWithOneSpace(spaceStart, spaceEnd, edits);
if (spaceStart != -1) {
availableLineWidth--;
parentConstraints.setAvailableLineWidth(availableLineWidth);
}
} else {
if (formatElementCategory == FormatElementCategory.NormalizeSpace
|| parentElement.getLastChild() == textNode) {
// Decrement indent level if is mixed content and text content is the last child
indentLevel--;
}
replaceLeftSpacesWithIndentationPreservedNewLines(spaceEnd, spaceStart, spaceEnd + 1, indentLevel,
edits);
}
}
}

private void replaceLeftSpacesWithIndentationPreservedNewLines(int contentStart, int spaceStart, int spaceEnd,
int indentLevel, List<TextEdit> edits) {
int preservedNewLines = getPreservedNewlines();
int currentNewLineCount = XMLFormatterDocumentNew.getExistingNewLineCount(
formatterDocument.getText(), contentStart, formatterDocument.getLineDelimiter());
if (currentNewLineCount > preservedNewLines) {
replaceLeftSpacesWithIndentationWithMultiNewLines(indentLevel, spaceStart,
spaceEnd, preservedNewLines + 1, edits);
} else {
int newLineCount = currentNewLineCount == 0 ? 1 : currentNewLineCount;
replaceLeftSpacesWithIndentationWithMultiNewLines(indentLevel, spaceStart, spaceEnd,
newLineCount, edits);
}
}

Expand All @@ -102,8 +153,8 @@ private int getMaxLineWidth() {
return formatterDocument.getMaxLineWidth();
}

private void insertLineBreak(int start, int end, List<TextEdit> edits) {
formatterDocument.insertLineBreak(start, end, edits);
private int getTabSize() {
return formatterDocument.getSharedSettings().getFormattingSettings().getTabSize();
}

private boolean isPreserveEmptyContent() {
Expand All @@ -114,7 +165,22 @@ private void replaceSpacesWithOneSpace(int spaceStart, int spaceEnd, List<TextEd
formatterDocument.replaceSpacesWithOneSpace(spaceStart, spaceEnd, edits);
}

private int replaceLeftSpacesWithIndentation(int indentLevel, int from, int to, boolean addLineSeparator,
List<TextEdit> edits) {
return formatterDocument.replaceLeftSpacesWithIndentation(indentLevel, from, to, addLineSeparator, edits);
}

private int replaceLeftSpacesWithIndentationWithMultiNewLines(int indentLevel, int from, int to, int newLineCount,
List<TextEdit> edits) {
return formatterDocument.replaceLeftSpacesWithIndentationWithMultiNewLines(indentLevel, from, to, newLineCount,
edits);
}

private boolean isJoinContentLines() {
return formatterDocument.getSharedSettings().getFormattingSettings().isJoinContentLines();
}

private int getPreservedNewlines() {
return formatterDocument.getSharedSettings().getFormattingSettings().getPreservedNewlines();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class XMLFormattingConstraints {

private int availableLineWidth = 0;
private int indentLevel = 0;
private int mixedContentIndentLevel = 0;

/**
* Initializes the values in this formatting constraint with values from
Expand All @@ -34,6 +35,7 @@ public void copyConstraints(XMLFormattingConstraints constraints) {
setFormatElementCategory(constraints.getFormatElementCategory());
setAvailableLineWidth(constraints.getAvailableLineWidth());
setIndentLevel(constraints.getIndentLevel());
setMixedContentIndentLevel(constraints.getMixedContentIndentLevel());
}

public FormatElementCategory getFormatElementCategory() {
Expand All @@ -60,4 +62,12 @@ public void setIndentLevel(int indentLevel) {
this.indentLevel = indentLevel;
}

public int getMixedContentIndentLevel() {
return mixedContentIndentLevel;
}

public void setMixedContentIndentLevel(int mixedContentIndentLevel) {
this.mixedContentIndentLevel = mixedContentIndentLevel;
}

}
Loading

0 comments on commit 719bf9d

Please sign in to comment.