Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR Version 1.8.0 #42

Merged
merged 3 commits into from Jun 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Expand Up @@ -3,7 +3,7 @@
# https://www.jetbrains.com/intellij-repository/snapshots

name='CSV Plugin'
pluginVersion=1.7.0
pluginVersion=1.8.0
javaVersion=1.8
javaTargetVersion=1.8
downloadIntellijSources=false
2 changes: 1 addition & 1 deletion intellij-csv-validator.iml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<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.8.0" relativePaths="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
Expand Down
121 changes: 96 additions & 25 deletions src/main/java/net/seesharpsoft/intellij/plugins/csv/CsvColumnInfo.java
@@ -1,25 +1,79 @@
package net.seesharpsoft.intellij.plugins.csv;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.NotNull;

import java.util.*;

public class CsvColumnInfo<T> {

public class RowInfo {
RowInfo(T element, int row) {
this(element, row, -1, -1);
}

RowInfo(@NotNull T element, @NotNull int row, int startIndex, int endIndex) {
this.element = element;
this.row = row;
if (startIndex <= endIndex && startIndex >= 0) {
this.textRange = TextRange.create(startIndex, endIndex);
} else {
this.textRange = null;
}
}

final T element;
final int row;
final TextRange textRange;

public T getElement() {
return element;
}

public int getRowIndex() {
return row;
}

public TextRange getTextRange() {
return textRange;
}

@Override
public int hashCode() {
return element.hashCode();
}

@Override
public boolean equals(Object other) {
if (!(other instanceof CsvColumnInfo.RowInfo)) {
return false;
}
return this.element.equals(((RowInfo) other).element);
}
}

private int columnIndex;
private int maxLength;
private Map<T, RowInfo> elementInfos;
private T headerElement;
private int size;

public CsvColumnInfo(int columnIndex, int maxLength) {
this.columnIndex = columnIndex;
this.maxLength = maxLength;
this.elements = new ArrayList<>();
this.elementInfos = new HashMap<>();
this.headerElement = null;
this.size = 0;
}

public RowInfo getRowInfo(T element) {
return elementInfos.get(element);
}

public int getColumnIndex() {
return columnIndex;
}

private int columnIndex;

private int maxLength;

public int getMaxLength() {
return maxLength;
}
Expand All @@ -28,36 +82,53 @@ public void setMaxLength(int maxLength) {
this.maxLength = maxLength;
}

private List<T> elements;
public int getSize() {
return this.size;
}

public List<T> getElements() {
return Collections.unmodifiableList(elements);
List<T> result = new ArrayList<>(getSize());
result.addAll(Collections.nCopies(getSize(), null));
elementInfos.values()
.forEach(rowInfo -> result.set(rowInfo.row, rowInfo.element));
return result;
}

public boolean addElement(T element) {
return elements.add(element);
protected void put(@NotNull T element, @NotNull RowInfo rowInfo) {
RowInfo previous = elementInfos.put(element, rowInfo);
if (this.getSize() <= rowInfo.row) {
this.size = rowInfo.row + 1;
}
if (rowInfo.row == 0) {
this.headerElement = element;
}
}

public void addElement(T element, int startIndex, int endIndex) {
this.put(element, new RowInfo(element, elementInfos.size(), startIndex, endIndex));
}

public void addElement(T element) {
this.addElement(element, -1, -1);
}

public void addElement(T element, int row, int startIndex, int endIndex) {
this.put(element, new RowInfo(element, row, startIndex, endIndex));
}

public void addElement(T element, int row) {
if (row == elements.size()) {
addElement(element);
} else if (row < elements.size()) {
elements.set(row, element);
} else {
elements.addAll(Collections.nCopies(row - elements.size(), null));
addElement(element);
}
this.addElement(element, row, -1, -1);
}

public boolean containsElement(T element) {
return elements.contains(element);
public boolean containsElement(T needle) {
return elementInfos.containsKey(needle);
}

public boolean isHeaderElement(T element) {
return elements.indexOf(element) == 0;
public boolean isHeaderElement(@NotNull T element) {
return element.equals(getHeaderElement());
}

public T getHeaderElement() {
return elements.size() > 0 ? elements.get(0) : null;
return this.headerElement;
}
}
Expand Up @@ -31,6 +31,11 @@ public CsvColumnInfo<T> getColumnInfo(int columnIndex) {
return infoColumnMap.get(columnIndex);
}

public CsvColumnInfo<T>.RowInfo getRowInfo(T element) {
CsvColumnInfo<T> columnInfo = getColumnInfo(element);
return columnInfo != null ? columnInfo.getRowInfo(element) : null;
}

public Map<Integer, CsvColumnInfo<T>> getColumnInfos() {
return Collections.unmodifiableMap(this.infoColumnMap);
}
Expand Down
Expand Up @@ -73,6 +73,64 @@ public static PsiElement getParentFieldElement(PsiElement element) {
return element;
}

public static PsiElement getPreviousCRLF(PsiElement recordElement) {
while (recordElement != null) {
if (CsvHelper.getElementType(recordElement) == CsvTypes.CRLF) {
break;
}
recordElement = recordElement.getPrevSibling();
}
return recordElement;
}

public static PsiElement getNextCRLF(PsiElement recordElement) {
while (recordElement != null) {
if (CsvHelper.getElementType(recordElement) == CsvTypes.CRLF) {
break;
}
recordElement = recordElement.getNextSibling();
}
return recordElement;
}

public static PsiElement getPreviousSeparator(PsiElement fieldElement) {
PsiElement current = fieldElement;
while (current != null) {
if (CsvHelper.getElementType(current) == CsvTypes.COMMA) {
break;
}
current = current.getPrevSibling();
}
return current;
}

public static PsiElement getNextSeparator(PsiElement fieldElement) {
PsiElement current = fieldElement;
while (current != null) {
if (CsvHelper.getElementType(current) == CsvTypes.COMMA) {
break;
}
current = current.getNextSibling();
}
return current;
}

public static int getFieldStartOffset(PsiElement field) {
PsiElement separator = CsvHelper.getPreviousSeparator(field);
if (separator == null) {
separator = getPreviousCRLF(field.getParent());
}
return separator == null ? 0 :separator.getTextOffset() + separator.getTextLength();
}

public static int getFieldEndOffset(PsiElement field) {
PsiElement separator = CsvHelper.getNextSeparator(field);
if (separator == null) {
separator = getNextCRLF(field.getParent());
}
return separator == null ? field.getContainingFile().getTextLength() : separator.getTextOffset();
}

public static CsvColumnInfoMap<PsiElement> createColumnInfoMap(CsvFile csvFile) {
Map<Integer, CsvColumnInfo<PsiElement>> columnInfoMap = new HashMap<>();
CsvRecord[] records = PsiTreeUtil.getChildrenOfType(csvFile, CsvRecord.class);
Expand All @@ -86,7 +144,7 @@ public static CsvColumnInfoMap<PsiElement> createColumnInfoMap(CsvFile csvFile)
} else if (columnInfoMap.get(column).getMaxLength() < length) {
columnInfoMap.get(column).setMaxLength(length);
}
columnInfoMap.get(column).addElement(field, row);
columnInfoMap.get(column).addElement(field, row, getFieldStartOffset(field), getFieldEndOffset(field));
++column;
}
++row;
Expand Down
@@ -1,13 +1,16 @@
package net.seesharpsoft.intellij.plugins.csv;
package net.seesharpsoft.intellij.plugins.csv.annotation;

import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.editor.markup.AttributesFlyweight;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.xml.util.XmlStringUtil;
import net.seesharpsoft.intellij.plugins.csv.CsvColumnInfo;
import net.seesharpsoft.intellij.plugins.csv.CsvHelper;
import net.seesharpsoft.intellij.plugins.csv.psi.CsvFile;
import net.seesharpsoft.intellij.plugins.csv.psi.CsvTypes;
import org.jetbrains.annotations.NotNull;
Expand All @@ -33,8 +36,12 @@ public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolde
PsiElement headerElement = columnInfo.getHeaderElement();
String message = XmlStringUtil.escapeString(headerElement == null ? "" : headerElement.getText(), true);
String tooltip = XmlStringUtil.wrapInHtml(String.format("%s<br /><br />Header: %s<br />Index: %d", XmlStringUtil.escapeString(element.getText(), true), message, columnInfo.getColumnIndex()));
TextRange textRange = columnInfo.getRowInfo(element).getTextRange();
if (textRange.getStartOffset() - csvFile.getTextLength() == 0 && textRange.getStartOffset() > 0) {
textRange = TextRange.from(textRange.getStartOffset() - 1, 1);
}

Annotation annotation = holder.createAnnotation(CSV_COLUMN_INFO_SEVERITY, element.getTextRange(), message, tooltip);
Annotation annotation = holder.createAnnotation(CSV_COLUMN_INFO_SEVERITY, textRange, message, tooltip);
annotation.setEnforcedTextAttributes(EMPTY_TEXT_ATTRIBUTES);
annotation.setNeedsUpdateOnTyping(false);
}
Expand Down
@@ -1,11 +1,14 @@
package net.seesharpsoft.intellij.plugins.csv.highlighter;

import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerBase;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.util.Consumer;
import net.seesharpsoft.intellij.plugins.csv.CsvColumnInfo;
import net.seesharpsoft.intellij.plugins.csv.CsvColumnInfoMap;
import net.seesharpsoft.intellij.plugins.csv.CsvHelper;
import net.seesharpsoft.intellij.plugins.csv.psi.CsvFile;
import org.jetbrains.annotations.NotNull;
Expand All @@ -26,13 +29,17 @@ protected CsvFile getCsvFile() {
@Override
public List<PsiElement> getTargets() {
Caret primaryCaret = this.myEditor.getCaretModel().getPrimaryCaret();
PsiElement myFocusedFieldElement = CsvHelper.getParentFieldElement(this.myFile.getViewProvider().findElementAt(primaryCaret.getOffset()));
PsiElement myFocusedElement = this.myFile.getViewProvider().findElementAt(primaryCaret.getOffset());
if (myFocusedElement == null) {
myFocusedElement = this.myFile.getLastChild();
}
myFocusedElement = CsvHelper.getParentFieldElement(myFocusedElement);

if (myFocusedFieldElement == null) {
if (myFocusedElement == null) {
return Collections.emptyList();
}

CsvColumnInfo<PsiElement> columnInfo = getCsvFile().getMyColumnInfoMap().getColumnInfo(myFocusedFieldElement);
CsvColumnInfo<PsiElement> columnInfo = getCsvFile().getMyColumnInfoMap().getColumnInfo(myFocusedElement);
return columnInfo == null ? Collections.emptyList() : Collections.unmodifiableList(columnInfo.getElements());
}

Expand All @@ -43,8 +50,21 @@ protected void selectTargets(List<PsiElement> list, Consumer<List<PsiElement>> c

@Override
public void computeUsages(List<PsiElement> list) {
CsvColumnInfoMap<PsiElement> columnInfoMap = getCsvFile().getMyColumnInfoMap();
list.forEach(element -> {
if (element != null && !element.getText().isEmpty()) { this.addOccurrence(element); }
if (element != null && !element.getText().isEmpty()) { this.addOccurrence(columnInfoMap.getRowInfo(element)); }
});
}

protected void addOccurrence(CsvColumnInfo<PsiElement>.RowInfo rowInfo) {
if (rowInfo == null) {
return;
}
TextRange range = rowInfo.getTextRange();
if (range != null) {
PsiElement element = rowInfo.getElement();
range = InjectedLanguageManager.getInstance(element.getProject()).injectedToHost(element, range);
this.myReadUsages.add(range);
}
}
}
@@ -1,4 +1,4 @@
package net.seesharpsoft.intellij.plugins.csv.intention;
package net.seesharpsoft.intellij.plugins.csv.inspection;

import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.InspectionSuppressor;
Expand Down
@@ -1,4 +1,4 @@
package net.seesharpsoft.intellij.plugins.csv.intention;
package net.seesharpsoft.intellij.plugins.csv.inspection;

import com.intellij.codeInspection.*;
import com.intellij.openapi.diagnostic.Logger;
Expand All @@ -12,6 +12,7 @@
import com.intellij.util.IncorrectOperationException;
import net.seesharpsoft.intellij.plugins.csv.CsvHelper;
import net.seesharpsoft.intellij.plugins.csv.CsvLanguage;
import net.seesharpsoft.intellij.plugins.csv.intention.CsvIntentionHelper;
import net.seesharpsoft.intellij.plugins.csv.psi.CsvTypes;
import net.seesharpsoft.intellij.plugins.csv.settings.CsvCodeStyleSettings;
import org.jetbrains.annotations.NonNls;
Expand Down