com.liferay.source.formatter.check.YMLWhitespaceCheck Maven / Gradle / Ivy
/**
* SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
*/
package com.liferay.source.formatter.check;
import com.liferay.petra.string.CharPool;
import com.liferay.petra.string.StringBundler;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.source.formatter.check.util.YMLSourceUtil;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Hugo Huijser
* @author Alan Huang
*/
public class YMLWhitespaceCheck extends WhitespaceCheck {
@Override
protected String doProcess(
String fileName, String absolutePath, String content)
throws IOException {
List contentBlocks = YMLSourceUtil.getContentBlocks(
content, _styleBlockPattern);
StringBundler sb = new StringBundler(contentBlocks.size() * 2);
for (int i = 0; i < contentBlocks.size(); i++) {
String contentBlock = contentBlocks.get(i);
if ((i % 2) != 0) {
sb.append(contentBlock);
sb.append(StringPool.NEW_LINE);
continue;
}
contentBlock = contentBlock.replaceAll(
"(\\{\\{)(?!(-| [^ ])[^\\}]*[^ ] \\}\\})( *)(?!-)(.*?) *(\\}" +
"\\})",
"$1 $4 $5");
contentBlock = StringUtil.replace(
contentBlock, CharPool.TAB, StringPool.FOUR_SPACES);
contentBlock = super.doProcess(
fileName, absolutePath, contentBlock);
if (contentBlock.startsWith("---") && (i != 0)) {
contentBlock = StringPool.NEW_LINE + contentBlock;
}
sb.append(contentBlock);
sb.append(StringPool.NEW_LINE);
}
sb.setIndex(sb.index() - 1);
content = _formatDefinitions(
fileName, sb.toString(), StringPool.BLANK, 0);
content = _formatSequencesAndMappings(content);
if (isAllowTrailingEmptyLines(fileName, absolutePath) &&
content.endsWith("\n")) {
return content;
}
return _formatWhitespace(content);
}
private String _formatDefinition(
String fileName, String definition, String[] definitionLines,
String indent, int level, boolean hasNestedDefinitions) {
String expectedIndent = StringPool.BLANK;
for (int j = 0; j < level; j++) {
expectedIndent = expectedIndent + StringPool.FOUR_SPACES;
}
String newDefinition = definition;
if (!expectedIndent.equals(indent)) {
newDefinition = expectedIndent + StringUtil.trimLeading(definition);
}
if (hasNestedDefinitions) {
return newDefinition;
}
if (definitionLines[0].endsWith("|-")) {
StringBundler sb = new StringBundler(definitionLines.length * 3);
for (String line : definitionLines) {
sb.append(expectedIndent);
sb.append(line.substring(indent.length()));
sb.append("\n");
}
sb.setIndex(sb.index() - 1);
return sb.toString();
}
if (definitionLines.length <= 1) {
return newDefinition;
}
String firstLine = definitionLines[1];
String newNestedContent = StringPool.BLANK;
String oldNestedContent = StringPool.BLANK;
String nestedIndent = firstLine.replaceAll("^(\\s+).+", "$1");
if (nestedIndent.equals(firstLine)) {
nestedIndent = StringPool.BLANK;
}
for (int j = 1; j < definitionLines.length; j++) {
String line = definitionLines[j];
if (j > 1) {
newNestedContent = newNestedContent + StringPool.NEW_LINE;
oldNestedContent = oldNestedContent + StringPool.NEW_LINE;
}
newNestedContent = newNestedContent + line;
oldNestedContent = oldNestedContent + line;
if (Validator.isNull(line)) {
continue;
}
String curIndent = line.replaceAll("^(\\s+).+", "$1");
if (curIndent.equals(line)) {
curIndent = StringPool.BLANK;
}
if (!curIndent.equals(nestedIndent)) {
continue;
}
String trimmedLine = StringUtil.trimLeading(line);
newNestedContent = StringUtil.replaceLast(
newNestedContent, line,
expectedIndent + StringPool.FOUR_SPACES + trimmedLine);
}
if (!newNestedContent.equals(oldNestedContent)) {
if (!_hasMapInsideList(definitionLines)) {
newDefinition = StringUtil.replaceFirst(
newDefinition, oldNestedContent, newNestedContent);
}
else {
String message = StringBundler.concat(
"Incorrect whitespace, expected '", expectedIndent,
" '\n", oldNestedContent);
addMessage(fileName, message);
}
}
return newDefinition;
}
private String _formatDefinitions(
String fileName, String content, String indent, int level) {
List definitions = YMLSourceUtil.getDefinitions(
content, indent);
String[] lines = content.split("\n");
int pos = lines[0].length();
for (String definition : definitions) {
lines = definition.split("\n");
if ((lines.length != 0) && lines[0].endsWith("|-")) {
String newDefinition = _formatDefinition(
fileName, definition, lines, indent, level, false);
if (!newDefinition.equals(definition)) {
content = StringUtil.replaceFirst(
content, definition, newDefinition, pos);
}
pos = pos + newDefinition.length();
continue;
}
String nestedDefinitionIndent =
YMLSourceUtil.getNestedDefinitionIndent(definition);
List nestedDefinitions = Collections.emptyList();
if (!nestedDefinitionIndent.equals(StringPool.BLANK)) {
nestedDefinitions = YMLSourceUtil.getDefinitions(
definition, nestedDefinitionIndent);
String newDefinition = _formatDefinitions(
fileName, definition, nestedDefinitionIndent, level + 1);
if (!newDefinition.equals(definition)) {
content = StringUtil.replaceFirst(
content, definition, newDefinition, 0);
definition = newDefinition;
}
}
lines = definition.split("\n");
String newDefinition = _formatDefinition(
fileName, definition, lines, indent, level,
!nestedDefinitions.isEmpty());
if (!newDefinition.equals(definition)) {
content = StringUtil.replaceFirst(
content, definition, newDefinition, pos);
}
pos = pos + newDefinition.length();
}
return content;
}
private String _formatSequencesAndMappings(String content) {
Matcher matcher = _mappingEntryPattern.matcher(content);
while (matcher.find()) {
String s = matcher.group();
String[] lines = s.split("\n");
if ((lines.length <= 1) ||
StringUtil.startsWith(lines[0].trim(), "- '")) {
continue;
}
StringBundler sb = new StringBundler();
for (int i = 1; i < lines.length; i++) {
sb.append(StringPool.NEW_LINE);
if (Validator.isNotNull(lines[i])) {
sb.append(lines[i].substring(2));
}
}
sb.append(StringPool.NEW_LINE);
String newContent = _formatSequencesAndMappings(sb.toString());
if (s.endsWith("\n\n")) {
newContent = newContent + "\n";
}
content = StringUtil.replaceFirst(
content, matcher.group(), lines[0] + newContent);
}
return content;
}
private String _formatWhitespace(String content) throws IOException {
StringBundler sb = new StringBundler();
try (UnsyncBufferedReader unsyncBufferedReader =
new UnsyncBufferedReader(new UnsyncStringReader(content))) {
String line = null;
while ((line = unsyncBufferedReader.readLine()) != null) {
line = formatIncorrectSyntax(line, "{ ", "{", false);
line = formatIncorrectSyntax(line, "[ ", "[", false);
String trimmedLine = StringUtil.trimLeading(line);
if (!trimmedLine.startsWith("}") &&
!trimmedLine.startsWith("]")) {
line = formatIncorrectSyntax(line, " }", "}", false);
line = formatIncorrectSyntax(line, " ]", "]", false);
}
sb.append(line);
sb.append("\n");
}
}
content = sb.toString();
if (content.endsWith("\n")) {
content = content.substring(0, content.length() - 1);
}
return content;
}
private boolean _hasMapInsideList(String[] lines) {
if (lines.length <= 1) {
return false;
}
String trimmedFirstLine = StringUtil.trimLeading(lines[1]);
if (!trimmedFirstLine.startsWith(StringPool.DASH)) {
return false;
}
for (int j = 1; j < lines.length; j++) {
String trimmedLine = StringUtil.trimLeading(lines[j]);
if (trimmedLine.matches("\\w+:.*")) {
return true;
}
}
return false;
}
private static final Pattern _mappingEntryPattern = Pattern.compile(
"^( *)- *?(\n|\\Z)((\\1 +.+)(\n|\\Z)+)+", Pattern.MULTILINE);
private static final Pattern _styleBlockPattern = Pattern.compile(
"(?<=\\|-)(?: *\n)(( +).*(\n\\2.*)*)");
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy