Skip to content

Commit e8c7d7a

Browse files
committed
[PERFORMANCE] improve formatter performance
1 parent 6b92d7a commit e8c7d7a

File tree

15 files changed

+97
-62
lines changed

15 files changed

+97
-62
lines changed

src/main/java/net/seesharpsoft/intellij/plugins/csv/formatter/CsvBlock.java

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import com.intellij.psi.TokenType;
66
import com.intellij.psi.formatter.common.AbstractBlock;
77
import com.intellij.psi.tree.IElementType;
8-
import net.seesharpsoft.intellij.plugins.csv.CsvColumnInfo;
98
import net.seesharpsoft.intellij.plugins.csv.psi.CsvTypes;
109
import org.jetbrains.annotations.NotNull;
1110
import org.jetbrains.annotations.Nullable;
@@ -23,49 +22,31 @@ protected CsvBlock(@NotNull ASTNode node, CsvFormattingInfo formattingInfo) {
2322

2423
@Override
2524
protected List<Block> buildChildren() {
26-
List<CsvBlock> blocks = buildChildrenInternal(getNode().getFirstChildNode());
27-
List<Block> result = new ArrayList<>();
28-
CsvColumnInfo currentColumnInfo = null;
29-
CsvBlockField currentField = null;
30-
for (CsvBlock block : blocks) {
31-
IElementType elementType = block.getElementType();
32-
CsvBlockElement blockElement = (CsvBlockElement)block;
33-
if (elementType == TokenType.WHITE_SPACE || elementType == CsvTypes.RECORD) {
34-
continue;
35-
} else if (elementType == CsvTypes.FIELD) {
36-
currentField = (CsvBlockField)block;
37-
currentColumnInfo = formattingInfo.getColumnInfo(block.getNode());
38-
}
39-
blockElement.setField(currentField);
40-
blockElement.setColumnInfo(currentColumnInfo);
41-
if (block.getTextLength() == 0) {
42-
continue;
43-
}
44-
result.add(block);
45-
}
46-
return result;
47-
}
48-
49-
private List<CsvBlock> buildChildrenInternal(ASTNode node) {
5025
List<ASTNode> todoNodes = new ArrayList<>();
51-
todoNodes.add(node);
52-
List<CsvBlock> blocks = new ArrayList<>();
26+
List<Block> blocks = new ArrayList<>();
27+
todoNodes.add(getNode().getFirstChildNode());
28+
CsvBlockField currentField = null;
5329
while (todoNodes.size() > 0) {
54-
node = todoNodes.remove(todoNodes.size() - 1);
30+
ASTNode node = todoNodes.remove(todoNodes.size() - 1);
5531
if (node == null) {
5632
continue;
5733
}
34+
5835
IElementType elementType = node.getElementType();
5936
if (elementType == TokenType.ERROR_ELEMENT || elementType == TokenType.BAD_CHARACTER) {
6037
break;
6138
}
39+
6240
todoNodes.add(node.getTreeNext());
63-
if (elementType == CsvTypes.FIELD) {
64-
blocks.add(new CsvBlockField(node, formattingInfo));
65-
} else {
66-
CsvBlockElement block = new CsvBlockElement(node, formattingInfo);
67-
blocks.add(block);
41+
if (elementType == CsvTypes.RECORD) {
6842
todoNodes.add(node.getFirstChildNode());
43+
} else if (elementType == CsvTypes.FIELD) {
44+
currentField = new CsvBlockField(node, formattingInfo);
45+
if (currentField.getTextLength() > 0) {
46+
blocks.add(currentField);
47+
}
48+
} else if (elementType == CsvTypes.COMMA || elementType == CsvTypes.CRLF) {
49+
blocks.add(new CsvBlockElement(node, formattingInfo, currentField));
6950
}
7051
}
7152
return blocks;

src/main/java/net/seesharpsoft/intellij/plugins/csv/formatter/CsvBlockElement.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,19 @@
1515
public class CsvBlockElement extends CsvBlock {
1616

1717
public CsvBlockElement(ASTNode node, CsvFormattingInfo formattingInfo) {
18+
this(node, formattingInfo, null);
19+
}
20+
21+
public CsvBlockElement(ASTNode node, CsvFormattingInfo formattingInfo, CsvBlockField field) {
1822
super(node, formattingInfo);
23+
setField(field);
1924
}
2025

21-
22-
protected CsvColumnInfo columnInfo;
23-
2426
public CsvColumnInfo getColumnInfo() {
25-
return columnInfo;
27+
return getField() == null ? null : getField().getColumnInfo();
2628
}
27-
28-
public void setColumnInfo(CsvColumnInfo columnInfo) {
29-
this.columnInfo = columnInfo;
30-
}
31-
32-
protected CsvBlockField field;
29+
30+
private CsvBlockField field;
3331

3432
public CsvBlockField getField() {
3533
return field;
@@ -48,7 +46,7 @@ protected List<Block> buildChildren() {
4846
public Indent getIndent() {
4947
if (formattingInfo.getCsvCodeStyleSettings().TABULARIZE
5048
&& (formattingInfo.getCsvCodeStyleSettings().LEADING_WHITE_SPACES || this.getElementType() == CsvTypes.COMMA)
51-
&& (formattingInfo.getCsvCodeStyleSettings().WHITE_SPACES_OUTSIDE_QUOTES || !CsvFormatHelper.isQuotedField(this))
49+
&& (formattingInfo.getCsvCodeStyleSettings().WHITE_SPACES_OUTSIDE_QUOTES || !CsvFormatHelper.isQuotedField(getField()))
5250
&& getField() != null) {
5351
CsvColumnInfo columnInfo = formattingInfo.getColumnInfo(0);
5452
return Indent.getSpaceIndent(columnInfo.getMaxLength() - getField().getTextLength() + getAdditionalSpaces(null, this));

src/main/java/net/seesharpsoft/intellij/plugins/csv/formatter/CsvBlockField.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.intellij.formatting.Spacing;
66
import com.intellij.lang.ASTNode;
77
import com.intellij.psi.TokenType;
8+
import net.seesharpsoft.intellij.plugins.csv.CsvColumnInfo;
89
import net.seesharpsoft.intellij.plugins.csv.psi.CsvTypes;
910
import org.jetbrains.annotations.NotNull;
1011
import org.jetbrains.annotations.Nullable;
@@ -13,18 +14,31 @@
1314
import java.util.List;
1415

1516
public class CsvBlockField extends CsvBlockElement {
16-
17+
18+
protected CsvColumnInfo columnInfo;
19+
1720
public CsvBlockField(ASTNode node, CsvFormattingInfo formattingInfo) {
18-
super(node, formattingInfo);
21+
super(node, formattingInfo, null);
22+
columnInfo = formattingInfo.getColumnInfo(node);
1923
}
2024

25+
@Override
26+
public CsvColumnInfo getColumnInfo() {
27+
return columnInfo;
28+
}
29+
30+
@Override
31+
public CsvBlockField getField() {
32+
return this;
33+
}
34+
2135
@Override
2236
protected List<Block> buildChildren() {
2337
ASTNode node = this.getNode().getFirstChildNode();
2438
List<Block> blocks = new ArrayList<>();
2539
while (node != null) {
2640
if (node.getElementType() != TokenType.WHITE_SPACE) {
27-
CsvBlockElement block = new CsvBlockElement(node, formattingInfo);
41+
CsvBlockElement block = new CsvBlockElement(node, formattingInfo, this);
2842
blocks.add(block);
2943
}
3044
node = node.getTreeNext();
@@ -43,7 +57,7 @@ public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) {
4357
CsvBlockElement block2 = (CsvBlockElement) child2;
4458
if ((block1.getElementType() == CsvTypes.QUOTE && formattingInfo.getCsvCodeStyleSettings().LEADING_WHITE_SPACES) ||
4559
(block2.getElementType() == CsvTypes.QUOTE && !formattingInfo.getCsvCodeStyleSettings().LEADING_WHITE_SPACES)) {
46-
spaces = columnInfo.getMaxLength() - getTextLength();
60+
spaces = getColumnInfo().getMaxLength() - getTextLength();
4761
} else {
4862
return formattingInfo.getSpacingBuilder().getSpacing(this, child1, child2);
4963
}
@@ -58,10 +72,8 @@ public int getTextLength() {
5872
@Override
5973
@Nullable
6074
public Indent getIndent() {
61-
Indent indent = super.getIndent();
62-
if (indent == null && !formattingInfo.getCsvCodeStyleSettings().TABULARIZE) {
63-
indent = Indent.getSpaceIndent(this.getNode().getStartOffset());
64-
}
65-
return indent;
75+
return formattingInfo.getCsvCodeStyleSettings().TABULARIZE || formattingInfo.getCsvCodeStyleSettings().TRIM_LEADING_WHITE_SPACES
76+
? null
77+
: Indent.getSpaceIndent(this.getNode().getStartOffset());
6678
}
6779
}

src/main/java/net/seesharpsoft/intellij/plugins/csv/formatter/CsvFormattingInfo.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
import com.intellij.psi.codeStyle.CodeStyleSettings;
66
import net.seesharpsoft.intellij.plugins.csv.CsvColumnInfo;
77

8+
import java.util.HashMap;
89
import java.util.Map;
910

1011
public class CsvFormattingInfo {
1112
private Map<Integer, CsvColumnInfo<ASTNode>> infoColumnMap;
13+
14+
private Map<ASTNode, CsvColumnInfo<ASTNode>> reverseInfoColumnMap;
1215

1316
public SpacingBuilder getSpacingBuilder() {
1417
return spacingBuilder;
@@ -30,15 +33,20 @@ public CsvFormattingInfo(CodeStyleSettings codeStyleSettings, SpacingBuilder spa
3033
this.infoColumnMap = infoColumnMap;
3134
this.spacingBuilder = spacingBuilder;
3235
this.codeStyleSettings = codeStyleSettings;
36+
buildReverseMap();
3337
}
34-
35-
public CsvColumnInfo getColumnInfo(ASTNode node) {
36-
for (CsvColumnInfo columnInfo : infoColumnMap.values()) {
37-
if (columnInfo.containsElement(node)) {
38-
return columnInfo;
38+
39+
private void buildReverseMap() {
40+
reverseInfoColumnMap = new HashMap<>();
41+
for (CsvColumnInfo<ASTNode> columnInfo : infoColumnMap.values()) {
42+
for (ASTNode node : columnInfo.getElements()) {
43+
reverseInfoColumnMap.put(node, columnInfo);
3944
}
4045
}
41-
return null;
46+
}
47+
48+
public CsvColumnInfo getColumnInfo(ASTNode node) {
49+
return reverseInfoColumnMap.get(node);
4250
}
4351

4452
public CsvColumnInfo getColumnInfo(int columnIndex) {

src/test/java/net/seesharpsoft/intellij/plugins/csv/formatter/CsvFormatterTest.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
66
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
77
import com.intellij.util.containers.ContainerUtil;
8+
import org.junit.Assert;
89

910
import java.io.PrintWriter;
11+
import java.time.Instant;
12+
import java.util.Properties;
1013

1114
public class CsvFormatterTest extends LightCodeInsightFixtureTestCase {
1215
@Override
@@ -48,6 +51,10 @@ private void initCsvCodeStyleSettings(int binarySettings) {
4851
}
4952

5053
private void executeTestConfiguration(int binarySettings, String relativeTargetPath) {
54+
executeTestConfiguration(binarySettings, relativeTargetPath, true);
55+
}
56+
57+
private void executeTestConfiguration(int binarySettings, String relativeTargetPath, boolean checkResults) {
5158
if (relativeTargetPath == null || relativeTargetPath.isEmpty()) {
5259
relativeTargetPath = ".";
5360
}
@@ -63,7 +70,9 @@ protected void run() throws Throwable {
6370
ContainerUtil.newArrayList(myFixture.getFile().getTextRange()));
6471
}
6572
}.execute();
66-
myFixture.checkResultByFile(relativeTargetPath + String.format("/TestResult%08d.csv", binarySettings));
73+
if (checkResults) {
74+
myFixture.checkResultByFile(relativeTargetPath + String.format("/TestResult%08d.csv", binarySettings));
75+
}
6776
}
6877

6978
public void testManualFormattedFiles() throws Exception {
@@ -96,7 +105,7 @@ public void testSpecialFormattedFiles() throws Exception {
96105
}
97106

98107
public void testHeader() throws Exception {
99-
int[] optionsToTest = new int[]{0, 1, 16, 17, 18, 19, 48, 80, 112};
108+
int[] optionsToTest = new int[]{0, 1, 4, 16, 17, 18, 19, 48, 80, 112};
100109
for (int subTest = 1; subTest < 7; ++subTest) {
101110
for (int i = 0; i < optionsToTest.length; ++i) {
102111
tearDown();
@@ -107,7 +116,20 @@ public void testHeader() throws Exception {
107116
}
108117

109118
public void testInvalidRangeException() throws Exception {
110-
executeTestConfiguration(0, "/InvalidRange");
119+
executeTestConfiguration(0, "/invalidRange");
120+
}
121+
122+
public void testRuntimeSimple() throws Exception {
123+
Long threshold = 1000l;
124+
Properties runtime = new Properties();
125+
runtime.load(this.getClass().getResourceAsStream("/formatter/performance/runtime.prop"));
126+
127+
long start = Instant.now().toEpochMilli();
128+
executeTestConfiguration(0, "/performance", false);
129+
long end = Instant.now().toEpochMilli();
130+
System.out.println(end - start);
131+
132+
Assert.assertTrue(end - start <= Long.parseLong(runtime.getProperty("00000000")) + threshold);
111133
}
112134

113135
/**
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
,
2+
0000000000,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
t,
2+
0000000000,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"t",
2+
0000000000,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
t ,
2+
0000000000,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"t" ,
2+
0000000000,

0 commit comments

Comments
 (0)