Skip to content

Commit 1d3cbeb

Browse files
authored
Merge pull request #345 from SeeSharpSoft/master
Release 2.21.0
2 parents 3d552df + 769ac72 commit 1d3cbeb

27 files changed

+575
-173
lines changed

CHANGELOG

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
2.21.0
2+
Oct 26, 2022
3+
4+
PERF: support comments in fast lexer
5+
PERF: reworked (rainbow) coloring
6+
PERF: avoid formatting while typing
7+
PERF: limit column highlighting to 1000 entries around caret
8+
PERF: limit calculation and buffering of CSV column info data
9+
FIX: short comments
10+
111
2.20.0
212
Oct 24, 2022
313

build.gradle

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jacocoTestReport {
1919
}
2020

2121
group 'net.seesharpsoft.intellij.plugins'
22-
version '2.20.0'
22+
version '2.21.0'
2323

2424
apply plugin: 'java'
2525
project.sourceCompatibility = JavaVersion.VERSION_11
@@ -77,10 +77,12 @@ intellij {
7777
}
7878
patchPluginXml {
7979
changeNotes = """<pre style="font-family: sans-serif">
80-
FIX: Cannot load from object array because "data" is null #335 #337
81-
NEW: Support fast lexing for default comments
82-
NEW: Simplify & unify both lexers
83-
FIX: Empty comment indicator
80+
PERF: support comments in fast lexer
81+
PERF: reworked (rainbow) coloring
82+
PERF: avoid formatting while typing
83+
PERF: limit column highlighting to 1000 entries around caret
84+
PERF: limit calculation and buffering of CSV column info data
85+
FIX: short comments
8486
</pre>"""
8587
}
8688
publishPlugin {

src/main/java/net/seesharpsoft/intellij/plugins/csv/CsvHelper.java

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import net.seesharpsoft.intellij.plugins.psv.PsvFileType;
2626
import net.seesharpsoft.intellij.plugins.tsv.TsvFileType;
2727
import org.jetbrains.annotations.NotNull;
28+
import org.jetbrains.annotations.Nullable;
2829

2930
import java.util.HashMap;
3031
import java.util.Map;
@@ -121,6 +122,36 @@ public static PsiElement getParentFieldElement(final PsiElement element) {
121122
return currentElement;
122123
}
123124

125+
public static int getFieldIndex(@NotNull final PsiElement element) {
126+
PsiElement fieldElement = getParentFieldElement(element);
127+
return findIndex(fieldElement.getParent(), fieldElement, CsvTypes.FIELD);
128+
}
129+
130+
@Nullable
131+
public static PsiElement getNthChild(@Nullable final PsiElement parent, int n, @Nullable IElementType countable) {
132+
if (parent != null) {
133+
int count = 0;
134+
for (PsiElement child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
135+
if (countable != null && getElementType(child) != countable) continue;
136+
if (count == n) return child;
137+
++count;
138+
}
139+
}
140+
return null;
141+
}
142+
143+
public static int findIndex(@Nullable final PsiElement parent, @NotNull PsiElement needle, @Nullable IElementType countable) {
144+
if (parent != null) {
145+
int index = 0;
146+
for (PsiElement child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
147+
if (countable != null && getElementType(child) != countable) continue;
148+
if (needle == child) return index;
149+
++index;
150+
}
151+
}
152+
return -1;
153+
}
154+
124155
public static PsiElement getPreviousCRLF(final PsiElement element) {
125156
PsiElement currentElement = element;
126157
while (currentElement != null) {
@@ -228,15 +259,17 @@ public static boolean hasEscapeCharacterAttribute(@NotNull PsiFile psiFile) {
228259
public static CsvColumnInfoMap<PsiElement> createColumnInfoMap(CsvFile csvFile) {
229260
CsvEscapeCharacter escapeCharacter = getEscapeCharacter(csvFile);
230261
Map<Integer, CsvColumnInfo<PsiElement>> columnInfoMap = new HashMap<>();
231-
CsvRecord[] records = PsiTreeUtil.getChildrenOfType(csvFile, CsvRecord.class);
232262
int row = 0;
233263
boolean hasComments = false;
234-
for (CsvRecord record : records) {
235-
// skip comment records
236-
if (record.getComment() != null) {
237-
hasComments = true;
264+
for (PsiElement child = csvFile.getFirstChild(); child != null; child = child.getNextSibling()) {
265+
if (!(child instanceof CsvRecord)) {
266+
if (getElementType(child) == CsvTypes.COMMENT) {
267+
hasComments = true;
268+
}
238269
continue;
239270
}
271+
272+
CsvRecord record = (CsvRecord) child;
240273
int column = 0;
241274
for (CsvField field : record.getFieldList()) {
242275
Integer length = CsvHelper.getMaxTextLineLength(unquoteCsvValue(field.getText(), escapeCharacter));

src/main/java/net/seesharpsoft/intellij/plugins/csv/CsvLexer.flex

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import com.intellij.lexer.FlexLexer;
1818
private boolean mySupportComments;
1919

2020
private boolean isActualValueSeparator() {
21-
return myValueSeparator.isValueSeparator(yytext().toString());
21+
return myValueSeparator.isValueSeparator(yycharat(0));
2222
}
2323

2424
/**
@@ -39,8 +39,9 @@ VALUE_SEPARATOR=[,:;|\t]
3939
RECORD_SEPARATOR=\n
4040
ESCAPED_QUOTE=\"\"|\\\"
4141
QUOTE=\"
42-
TEXT=[^ ,:;|\t\r\n\"\\]+
42+
TEXT=[^ ,:;|\t\r\n\"\\#]+
4343
BACKSLASH=\\+
44+
HASHTAG=#
4445
COMMENT=\#[^\n]*
4546

4647
%state UNQUOTED
@@ -91,6 +92,11 @@ COMMENT=\#[^\n]*
9192
return CsvTypes.TEXT;
9293
}
9394

95+
<UNQUOTED, QUOTED> {HASHTAG}
96+
{
97+
return CsvTypes.TEXT;
98+
}
99+
94100
<QUOTED> {TEXT}
95101
{
96102
return CsvTypes.TEXT;

src/main/java/net/seesharpsoft/intellij/plugins/csv/CsvParserDefinition.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
public class CsvParserDefinition implements FileParserDefinition {
2121
public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE);
2222

23+
public static final TokenSet STRING_LITERALS = TokenSet.create(CsvTypes.TEXT, CsvTypes.ESCAPED_TEXT);
24+
2325
public static final IFileElementType FILE = new CsvFileElementType(CsvLanguage.INSTANCE);
2426

2527
@NotNull
@@ -43,7 +45,7 @@ public TokenSet getCommentTokens() {
4345
@Override
4446
@NotNull
4547
public TokenSet getStringLiteralElements() {
46-
return TokenSet.EMPTY;
48+
return STRING_LITERALS;
4749
}
4850

4951
@Override

src/main/java/net/seesharpsoft/intellij/plugins/csv/CsvValueSeparator.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ public boolean isValueSeparator(String text) {
101101
return myPattern.matcher(text).matches();
102102
}
103103

104+
public boolean isValueSeparator(char c) {
105+
return myCharacter.charAt(0) == c;
106+
}
107+
104108
public String getName() {
105109
return myName;
106110
}

src/main/java/net/seesharpsoft/intellij/plugins/csv/editor/CsvAnnotator.java

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,9 @@
77
import com.intellij.psi.PsiElement;
88
import com.intellij.psi.tree.IElementType;
99
import com.intellij.xml.util.XmlStringUtil;
10-
import net.seesharpsoft.intellij.plugins.csv.CsvColumnInfo;
1110
import net.seesharpsoft.intellij.plugins.csv.CsvHelper;
1211
import net.seesharpsoft.intellij.plugins.csv.CsvValueSeparator;
13-
import net.seesharpsoft.intellij.plugins.csv.psi.CsvFile;
14-
import net.seesharpsoft.intellij.plugins.csv.psi.CsvTypes;
15-
import net.seesharpsoft.intellij.plugins.csv.settings.CsvColorSettings;
12+
import net.seesharpsoft.intellij.plugins.csv.psi.*;
1613
import net.seesharpsoft.intellij.plugins.csv.settings.CsvEditorSettings;
1714
import org.jetbrains.annotations.NotNull;
1815

@@ -40,41 +37,38 @@ public void annotate(@NotNull final PsiElement element, @NotNull final Annotatio
4037
return;
4138
}
4239

43-
CsvColumnInfo<PsiElement> columnInfo = csvFile.getColumnInfoMap().getColumnInfo(element);
44-
45-
if (columnInfo != null) {
46-
PsiElement headerElement = columnInfo.getHeaderElement();
40+
if (showInfoBalloon(holder.getCurrentAnnotationSession())) {
41+
int fieldIndex = CsvHelper.getFieldIndex(element);
42+
String header = getHeaderText(csvFile, fieldIndex);
4743
String message = FontUtil.getHtmlWithFonts(
48-
XmlStringUtil.escapeString(headerElement == null ? "" : headerElement.getText(), true)
44+
XmlStringUtil.escapeString(header, true)
45+
);
46+
String tooltip = XmlStringUtil.wrapInHtml(
47+
String.format("%s<br /><br />Header: %s<br />Index: %d",
48+
FontUtil.getHtmlWithFonts(
49+
XmlStringUtil.escapeString(element.getText(), true)
50+
),
51+
message,
52+
fieldIndex + (CsvEditorSettings.getInstance().isZeroBasedColumnNumbering() ? 0 : 1)
53+
)
4954
);
50-
String tooltip = null;
51-
if (showInfoBalloon(holder.getCurrentAnnotationSession())) {
52-
tooltip = XmlStringUtil.wrapInHtml(
53-
String.format("%s<br /><br />Header: %s<br />Index: %d",
54-
FontUtil.getHtmlWithFonts(
55-
XmlStringUtil.escapeString(element.getText(), true)
56-
),
57-
message,
58-
columnInfo.getColumnIndex() + (CsvEditorSettings.getInstance().isZeroBasedColumnNumbering() ? 0 : 1)
59-
)
60-
);
61-
}
6255

6356
AnnotationBuilder annotationBuilder = holder.newAnnotation(CSV_COLUMN_INFO_SEVERITY, message)
6457
.range(element)
6558
.needsUpdateOnTyping(false);
6659

67-
if (CsvEditorSettings.getInstance().getValueColoring() == CsvEditorSettings.ValueColoring.RAINBOW) {
68-
annotationBuilder.enforcedTextAttributes(CsvColorSettings.getTextAttributesOfColumn(columnInfo.getColumnIndex(), holder.getCurrentAnnotationSession()));
69-
}
7060
if (tooltip != null) {
7161
annotationBuilder.tooltip(tooltip);
7262
}
73-
7463
annotationBuilder.create();
7564
}
7665
}
7766

67+
protected String getHeaderText(@NotNull final CsvFile csvFile, int index) {
68+
PsiElement nthChild = CsvHelper.getNthChild(csvFile.getFirstChild(), index, CsvTypes.FIELD);
69+
return nthChild instanceof CsvField ? nthChild.getText() : "";
70+
}
71+
7872
protected boolean showInfoBalloon(@NotNull AnnotationSession annotationSession) {
7973
Boolean showInfoBalloon = annotationSession.getUserData(SHOW_INFO_BALLOON_KEY);
8074
if (showInfoBalloon == null) {
@@ -94,8 +88,8 @@ protected boolean handleSeparatorElement(@NotNull PsiElement element, @NotNull A
9488
CsvEditorSettings.getInstance().getTabHighlightColor(),
9589
null, null, 0);
9690
holder.getCurrentAnnotationSession().putUserData(TAB_SEPARATOR_HIGHLIGHT_COLOR_KEY, textAttributes);
97-
holder.getCurrentAnnotationSession().putUserData(TAB_SEPARATOR_HIGHLIGHT_COLOR_DETERMINED_KEY, Boolean.TRUE);
9891
}
92+
holder.getCurrentAnnotationSession().putUserData(TAB_SEPARATOR_HIGHLIGHT_COLOR_DETERMINED_KEY, Boolean.TRUE);
9993
}
10094
if (textAttributes != null && showInfoBalloon(holder.getCurrentAnnotationSession())) {
10195
holder.newAnnotation(CSV_COLUMN_INFO_SEVERITY, "↹")

src/main/java/net/seesharpsoft/intellij/plugins/csv/editor/table/CsvTableEditor.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.google.common.primitives.Ints;
44
import com.intellij.codeHighlighting.BackgroundEditorHighlighter;
55
import com.intellij.ide.structureView.StructureViewBuilder;
6+
import com.intellij.openapi.Disposable;
67
import com.intellij.openapi.application.ApplicationManager;
78
import com.intellij.openapi.command.CommandProcessor;
89
import com.intellij.openapi.editor.Document;
@@ -35,10 +36,12 @@
3536
import java.util.List;
3637
import java.util.Map;
3738

38-
public abstract class CsvTableEditor implements FileEditor, FileEditorLocation {
39+
public abstract class CsvTableEditor implements FileEditor, FileEditorLocation, Disposable {
3940

4041
public static final String EDITOR_NAME = "Table Editor";
4142

43+
private boolean myDisposed = false;
44+
4245
protected final Project project;
4346
protected final VirtualFile file;
4447
protected final UserDataHolder userDataHolder;
@@ -222,7 +225,7 @@ public boolean isModified() {
222225

223226
@Override
224227
public boolean isValid() {
225-
if (file == null || !file.isValid()) {
228+
if (this.isDisposed() || file == null || !file.isValid()) {
226229
return false;
227230
}
228231
CsvFile csvFile = this.getCsvFile();
@@ -273,7 +276,14 @@ public FileEditorLocation getCurrentLocation() {
273276

274277
@Override
275278
public void dispose() {
279+
if (this.isDisposed()) return;
280+
276281
this.deselectNotify();
282+
this.myDisposed = true;
283+
}
284+
285+
public boolean isDisposed() {
286+
return this.myDisposed;
277287
}
278288

279289
@Nullable

src/main/java/net/seesharpsoft/intellij/plugins/csv/editor/table/swing/CsvTableEditorSwing.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import net.seesharpsoft.intellij.plugins.csv.editor.table.api.TableActions;
1818
import net.seesharpsoft.intellij.plugins.csv.editor.table.api.TableDataChangeEvent;
1919
import net.seesharpsoft.intellij.plugins.csv.psi.CsvFile;
20-
import net.seesharpsoft.intellij.util.DisposerAwareRunnable;
20+
import net.seesharpsoft.intellij.util.CheckedDisposableAwareRunnable;
2121
import org.jetbrains.annotations.NotNull;
2222
import org.jetbrains.annotations.Nullable;
2323

@@ -96,6 +96,8 @@ protected void createUIComponents() {
9696
}
9797

9898
private void initializedUIComponents() {
99+
applyEditorState(getFileEditorState());
100+
99101
EditorColorsScheme editorColorsScheme = EditorColorsManager.getInstance().getGlobalScheme();
100102

101103
btnRedo.addActionListener(tableEditorActions.redo);
@@ -155,13 +157,11 @@ private void initializedUIComponents() {
155157
setFontSize(getGlobalFontSize());
156158
baseFontHeight = getFontHeight();
157159

158-
applyEditorState(getFileEditorState());
159-
160160
rowHeadersTable = TableRowUtilities.addNumberColumn(tblEditor, 1);
161161
}
162162

163163
protected void applyTableChangeListener() {
164-
if (!listenerApplied && isEditable()) {
164+
if (!listenerApplied && isEditorSelected() && isEditable()) {
165165
listenerApplied = true;
166166
tblEditor.getModel().addTableModelListener(tableEditorListener);
167167
tblEditor.addMouseListener(this.tableEditorMouseListener);
@@ -249,7 +249,7 @@ public void updateRowHeights(TableModelEvent e) {
249249
last = e.getLastRow() + 1;
250250
}
251251

252-
SwingUtilities.invokeLater(DisposerAwareRunnable.create(() -> updateRowHeights(first, last), this));
252+
SwingUtilities.invokeLater(CheckedDisposableAwareRunnable.create(() -> updateRowHeights(first, last), this));
253253
}
254254

255255
private void updateRowHeights(int first, int last) {

0 commit comments

Comments
 (0)