Skip to content

Commit 934e734

Browse files
authored
Merge pull request #34 from SeeSharpSoft/master
Release 1.7.0
2 parents 0b33c3a + 5e48ae5 commit 934e734

40 files changed

+478
-179
lines changed

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# https://www.jetbrains.com/intellij-repository/snapshots
44

55
name='CSV Plugin'
6-
pluginVersion=1.6.1
6+
pluginVersion=1.7.0
77
javaVersion=1.8
88
javaTargetVersion=1.8
99
downloadIntellijSources=false

intellij-csv-validator.iml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<module external.linked.project.id="intellij-csv-validator" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="net.seesharpsoft.intellij.plugins" external.system.module.version="1.6.1" relativePaths="true" type="JAVA_MODULE" version="4">
2+
<module external.linked.project.id="intellij-csv-validator" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="net.seesharpsoft.intellij.plugins" external.system.module.version="1.7.0" relativePaths="true" type="JAVA_MODULE" version="4">
33
<component name="NewModuleRootManager" inherit-compiler-output="true">
44
<exclude-output />
55
<content url="file://$MODULE_DIR$">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package net.seesharpsoft.intellij.plugins.csv;
2+
3+
import com.intellij.lang.annotation.Annotation;
4+
import com.intellij.lang.annotation.AnnotationHolder;
5+
import com.intellij.lang.annotation.Annotator;
6+
import com.intellij.lang.annotation.HighlightSeverity;
7+
import com.intellij.openapi.editor.markup.AttributesFlyweight;
8+
import com.intellij.openapi.editor.markup.TextAttributes;
9+
import com.intellij.psi.PsiElement;
10+
import com.intellij.xml.util.XmlStringUtil;
11+
import net.seesharpsoft.intellij.plugins.csv.psi.CsvFile;
12+
import net.seesharpsoft.intellij.plugins.csv.psi.CsvTypes;
13+
import org.jetbrains.annotations.NotNull;
14+
15+
public class CsvAnnotator implements Annotator {
16+
17+
private static final TextAttributes EMPTY_TEXT_ATTRIBUTES = TextAttributes.fromFlyweight(AttributesFlyweight.create(null, null, 0, null, null, null));
18+
19+
@Override
20+
public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
21+
if (CsvHelper.getElementType(element) != CsvTypes.FIELD || !(element.getContainingFile() instanceof CsvFile)) {
22+
return;
23+
}
24+
25+
CsvFile csvFile = (CsvFile)element.getContainingFile();
26+
CsvColumnInfo<PsiElement> columnInfo = csvFile.getMyColumnInfoMap().getColumnInfo(element);
27+
28+
if (columnInfo != null) {
29+
PsiElement headerElement = columnInfo.getHeaderElement();
30+
String message = XmlStringUtil.escapeString(headerElement == null ? "" : headerElement.getText(), true);
31+
String tooltip = XmlStringUtil.wrapInHtml(String.format("%s<br /><br />Header: %s<br />Index: %d", XmlStringUtil.escapeString(element.getText(), true), message, columnInfo.getColumnIndex()));
32+
33+
Annotation annotation = holder.createAnnotation(HighlightSeverity.INFORMATION, element.getTextRange(), message, tooltip);
34+
annotation.setEnforcedTextAttributes(EMPTY_TEXT_ATTRIBUTES);
35+
annotation.setNeedsUpdateOnTyping(false);
36+
}
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package net.seesharpsoft.intellij.plugins.csv;
2+
3+
import java.util.Collections;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
7+
public class CsvColumnInfoMap<T> {
8+
9+
private final Map<Integer, CsvColumnInfo<T>> infoColumnMap;
10+
private final Map<T, CsvColumnInfo<T>> reverseInfoColumnMap;
11+
12+
public CsvColumnInfoMap(Map<Integer, CsvColumnInfo<T>> infoColumnMap) {
13+
this.infoColumnMap = infoColumnMap;
14+
this.reverseInfoColumnMap = new HashMap<>();
15+
buildReverseMap();
16+
}
17+
18+
private void buildReverseMap() {
19+
for (CsvColumnInfo<T> columnInfo : this.infoColumnMap.values()) {
20+
for (T element : columnInfo.getElements()) {
21+
this.reverseInfoColumnMap.put(element, columnInfo);
22+
}
23+
}
24+
}
25+
26+
public CsvColumnInfo<T> getColumnInfo(T element) {
27+
return reverseInfoColumnMap.get(element);
28+
}
29+
30+
public CsvColumnInfo<T> getColumnInfo(int columnIndex) {
31+
return infoColumnMap.get(columnIndex);
32+
}
33+
34+
public Map<Integer, CsvColumnInfo<T>> getColumnInfos() {
35+
return Collections.unmodifiableMap(this.infoColumnMap);
36+
}
37+
}

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

+64-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,79 @@
11
package net.seesharpsoft.intellij.plugins.csv;
22

3+
import com.intellij.lang.*;
4+
import com.intellij.lexer.Lexer;
5+
import com.intellij.openapi.project.Project;
36
import com.intellij.psi.PsiElement;
7+
import com.intellij.psi.PsiManager;
8+
import com.intellij.psi.TokenType;
9+
import com.intellij.psi.impl.source.DummyHolder;
10+
import com.intellij.psi.impl.source.DummyHolderFactory;
11+
import com.intellij.psi.impl.source.tree.FileElement;
12+
import com.intellij.psi.tree.IElementType;
413
import com.intellij.psi.util.PsiTreeUtil;
514
import net.seesharpsoft.intellij.plugins.csv.psi.CsvField;
615
import net.seesharpsoft.intellij.plugins.csv.psi.CsvFile;
716
import net.seesharpsoft.intellij.plugins.csv.psi.CsvRecord;
17+
import net.seesharpsoft.intellij.plugins.csv.psi.CsvTypes;
818

919
import java.util.HashMap;
1020
import java.util.Map;
1121

1222
public class CsvHelper {
1323

14-
public static Map<Integer, CsvColumnInfo<PsiElement>> createColumnInfoMap(CsvFile csvFile) {
24+
// replaces PsiElementFactory.SERVICE.getInstance(element.getProject()).createDummyHolder("<undefined>", CsvTypes.FIELD, null);
25+
// https://github.com/SeeSharpSoft/intellij-csv-validator/issues/4
26+
public static PsiElement createEmptyCsvField(Project project) {
27+
final String text = "<undefined>";
28+
final IElementType type = CsvTypes.FIELD;
29+
final PsiManager psiManager = PsiManager.getInstance(project);
30+
final DummyHolder dummyHolder = DummyHolderFactory.createHolder(psiManager, null);
31+
final FileElement fileElement = dummyHolder.getTreeElement();
32+
final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(CsvLanguage.INSTANCE);
33+
final Lexer lexer = parserDefinition.createLexer(project);
34+
final PsiBuilder psiBuilder = PsiBuilderFactory.getInstance().createBuilder(project, fileElement, lexer, CsvLanguage.INSTANCE, text);
35+
final ASTNode node = parserDefinition.createParser(project).parse(type, psiBuilder);
36+
fileElement.rawAddChildren((com.intellij.psi.impl.source.tree.TreeElement)node);
37+
return node.getPsi();
38+
}
39+
40+
public static IElementType getElementType(PsiElement element) {
41+
return element == null || element.getNode() == null ? null : element.getNode().getElementType();
42+
}
43+
44+
public static PsiElement getParentFieldElement(PsiElement element) {
45+
IElementType elementType = CsvHelper.getElementType(element);
46+
47+
if(elementType == CsvTypes.COMMA || elementType == CsvTypes.CRLF) {
48+
element = element.getPrevSibling();
49+
elementType = CsvHelper.getElementType(element);
50+
}
51+
52+
if(elementType == CsvTypes.RECORD) {
53+
element = element.getLastChild();
54+
elementType = CsvHelper.getElementType(element);
55+
}
56+
57+
if (elementType == TokenType.WHITE_SPACE) {
58+
if (CsvHelper.getElementType(element.getParent()) == CsvTypes.FIELD) {
59+
element = element.getParent();
60+
} else if (CsvHelper.getElementType(element.getPrevSibling()) == CsvTypes.FIELD) {
61+
element = element.getPrevSibling();
62+
} else if (CsvHelper.getElementType(element.getNextSibling()) == CsvTypes.FIELD) {
63+
element = element.getNextSibling();
64+
} else {
65+
element = null;
66+
}
67+
} else {
68+
while (element != null && elementType != CsvTypes.FIELD) {
69+
element = element.getParent();
70+
elementType = CsvHelper.getElementType(element);
71+
}
72+
}
73+
return element;
74+
}
75+
76+
public static CsvColumnInfoMap<PsiElement> createColumnInfoMap(CsvFile csvFile) {
1577
Map<Integer, CsvColumnInfo<PsiElement>> columnInfoMap = new HashMap<>();
1678
CsvRecord[] records = PsiTreeUtil.getChildrenOfType(csvFile, CsvRecord.class);
1779
int row = 0;
@@ -29,7 +91,6 @@ public static Map<Integer, CsvColumnInfo<PsiElement>> createColumnInfoMap(CsvFil
2991
}
3092
++row;
3193
}
32-
return columnInfoMap;
94+
return new CsvColumnInfoMap(columnInfoMap);
3395
}
34-
3596
}

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

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import com.intellij.lexer.FlexLexer;
44
import com.intellij.psi.tree.IElementType;
55
import com.intellij.openapi.project.Project;
66
import net.seesharpsoft.intellij.plugins.csv.psi.CsvTypes;
7-
import static net.seesharpsoft.intellij.plugins.csv.settings.CsvCodeStyleSettings.getCurrentSeparator;
87
import com.intellij.psi.TokenType;
98

109
%%

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

+4-26
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,13 @@
33
import com.intellij.formatting.SpacingBuilder;
44
import com.intellij.lang.ASTNode;
55
import com.intellij.psi.codeStyle.CodeStyleSettings;
6-
import net.seesharpsoft.intellij.plugins.csv.settings.CsvCodeStyleSettings;
76
import net.seesharpsoft.intellij.plugins.csv.CsvColumnInfo;
7+
import net.seesharpsoft.intellij.plugins.csv.CsvColumnInfoMap;
8+
import net.seesharpsoft.intellij.plugins.csv.settings.CsvCodeStyleSettings;
89

9-
import java.util.HashMap;
1010
import java.util.Map;
1111

12-
public class CsvFormattingInfo {
13-
private Map<Integer, CsvColumnInfo<ASTNode>> infoColumnMap;
14-
15-
private Map<ASTNode, CsvColumnInfo<ASTNode>> reverseInfoColumnMap;
12+
public class CsvFormattingInfo extends CsvColumnInfoMap<ASTNode> {
1613

1714
public SpacingBuilder getSpacingBuilder() {
1815
return spacingBuilder;
@@ -31,27 +28,8 @@ public CodeStyleSettings getCodeStyleSettings() {
3128
private CodeStyleSettings codeStyleSettings;
3229

3330
public CsvFormattingInfo(CodeStyleSettings codeStyleSettings, SpacingBuilder spacingBuilder, Map<Integer, CsvColumnInfo<ASTNode>> infoColumnMap) {
34-
this.infoColumnMap = infoColumnMap;
31+
super(infoColumnMap);
3532
this.spacingBuilder = spacingBuilder;
3633
this.codeStyleSettings = codeStyleSettings;
37-
buildReverseMap();
38-
}
39-
40-
private void buildReverseMap() {
41-
reverseInfoColumnMap = new HashMap<>();
42-
for (CsvColumnInfo<ASTNode> columnInfo : infoColumnMap.values()) {
43-
for (ASTNode node : columnInfo.getElements()) {
44-
reverseInfoColumnMap.put(node, columnInfo);
45-
}
46-
}
47-
}
48-
49-
public CsvColumnInfo getColumnInfo(ASTNode node) {
50-
return reverseInfoColumnMap.get(node);
51-
}
52-
53-
public CsvColumnInfo getColumnInfo(int columnIndex) {
54-
return infoColumnMap.get(columnIndex);
5534
}
56-
5735
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package net.seesharpsoft.intellij.plugins.csv.highlighter;
2+
3+
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerBase;
4+
import com.intellij.openapi.editor.Caret;
5+
import com.intellij.openapi.editor.Editor;
6+
import com.intellij.psi.PsiElement;
7+
import com.intellij.util.Consumer;
8+
import net.seesharpsoft.intellij.plugins.csv.CsvColumnInfo;
9+
import net.seesharpsoft.intellij.plugins.csv.CsvHelper;
10+
import net.seesharpsoft.intellij.plugins.csv.psi.CsvFile;
11+
import org.jetbrains.annotations.NotNull;
12+
13+
import java.util.Collections;
14+
import java.util.List;
15+
16+
public class CsvHighlightUsagesHandler extends HighlightUsagesHandlerBase<PsiElement> {
17+
18+
protected CsvHighlightUsagesHandler(@NotNull Editor editor, @NotNull CsvFile file) {
19+
super(editor, file);
20+
}
21+
22+
protected CsvFile getCsvFile() {
23+
return (CsvFile)this.myFile;
24+
}
25+
26+
@Override
27+
public List<PsiElement> getTargets() {
28+
Caret primaryCaret = this.myEditor.getCaretModel().getPrimaryCaret();
29+
PsiElement myFocusedFieldElement = CsvHelper.getParentFieldElement(this.myFile.getViewProvider().findElementAt(primaryCaret.getOffset()));
30+
31+
if (myFocusedFieldElement == null) {
32+
return Collections.emptyList();
33+
}
34+
35+
CsvColumnInfo<PsiElement> columnInfo = getCsvFile().getMyColumnInfoMap().getColumnInfo(myFocusedFieldElement);
36+
return columnInfo == null ? Collections.emptyList() : Collections.unmodifiableList(columnInfo.getElements());
37+
}
38+
39+
@Override
40+
protected void selectTargets(List<PsiElement> list, Consumer<List<PsiElement>> consumer) {
41+
consumer.consume(list);
42+
}
43+
44+
@Override
45+
public void computeUsages(List<PsiElement> list) {
46+
list.forEach(element -> {
47+
if (element != null && !element.getText().isEmpty()) { this.addOccurrence(element); }
48+
});
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package net.seesharpsoft.intellij.plugins.csv.highlighter;
2+
3+
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerBase;
4+
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerFactory;
5+
import com.intellij.openapi.editor.Editor;
6+
import com.intellij.psi.PsiFile;
7+
import net.seesharpsoft.intellij.plugins.csv.psi.CsvFile;
8+
import org.jetbrains.annotations.NotNull;
9+
import org.jetbrains.annotations.Nullable;
10+
11+
public class CsvHighlightUsagesHandlerFactory implements HighlightUsagesHandlerFactory {
12+
@Nullable
13+
@Override
14+
public HighlightUsagesHandlerBase createHighlightUsagesHandler(@NotNull Editor editor, @NotNull PsiFile psiFile) {
15+
if (psiFile instanceof CsvFile) {
16+
return new CsvHighlightUsagesHandler(editor, (CsvFile)psiFile);
17+
}
18+
return null;
19+
}
20+
}

0 commit comments

Comments
 (0)