Merge branch 'inspections'

GitOrigin-RevId: d4b448a942efea35ebed9ede22082626e888b93f
This commit is contained in:
adelf
2021-10-18 14:45:47 +03:00
committed by intellij-monorepo-bot
10 changed files with 302 additions and 0 deletions

View File

@@ -15,6 +15,14 @@ import ru.adelf.idea.dotenv.psi.DotEnvFile;
import java.util.*;
public class DuplicateKeyInspection extends LocalInspectionTool {
// Change the display name within the plugin.xml
// This needs to be here as otherwise the tests will throw errors.
@NotNull
@Override
public String getDisplayName() {
return "Duplicate Key";
}
@Override
public boolean runForWholeFile() {
return true;

View File

@@ -0,0 +1,91 @@
package ru.adelf.idea.dotenv.inspections;
import com.intellij.codeInspection.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import ru.adelf.idea.dotenv.DotEnvFactory;
import ru.adelf.idea.dotenv.psi.DotEnvFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ExtraBlankLineInspection extends LocalInspectionTool {
// Change the display name within the plugin.xml
// This needs to be here as otherwise the tests will throw errors.
@NotNull
@Override
public String getDisplayName() {
return "Extra blank line";
}
@Override
public boolean runForWholeFile() {
return true;
}
@Nullable
@Override
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
if (!(file instanceof DotEnvFile)) {
return null;
}
return analyzeFile(file, manager, isOnTheFly).getResultsArray();
}
@NotNull
private ProblemsHolder analyzeFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
ProblemsHolder problemsHolder = new ProblemsHolder(manager, file, isOnTheFly);
PsiTreeUtil.findChildrenOfType(file, PsiWhiteSpaceImpl.class).forEach(whiteSpace -> {
Pattern pattern = Pattern.compile("\r\n|\r|\n");
Matcher matcher = pattern.matcher(whiteSpace.getText());
int count = 0;
while (matcher.find())
count++;
if (count > 2) {
problemsHolder.registerProblem(whiteSpace,
"Only one extra line allowed between properties",
new RemoveExtraBlankLineQuickFix());
}
});
return problemsHolder;
}
private static class RemoveExtraBlankLineQuickFix implements LocalQuickFix {
@NotNull
@Override
public String getName() {
return "Remove extra blank line";
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
try {
PsiElement psiElement = descriptor.getPsiElement();
PsiElement newPsiElement = DotEnvFactory.createFromText(project, ElementType.WHITE_SPACE, "\n\n");
psiElement.replace(newPsiElement);
} catch (IncorrectOperationException e) {
Logger.getInstance(ExtraBlankLineInspection.class).error(e);
}
}
@NotNull
public String getFamilyName() {
return getName();
}
}
}

View File

@@ -0,0 +1,80 @@
package ru.adelf.idea.dotenv.inspections;
import com.intellij.codeInspection.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import ru.adelf.idea.dotenv.DotEnvFactory;
import ru.adelf.idea.dotenv.psi.DotEnvFile;
import ru.adelf.idea.dotenv.psi.DotEnvTypes;
import ru.adelf.idea.dotenv.psi.impl.DotEnvKeyImpl;
public class IncorrectDelimiterInspection extends LocalInspectionTool {
// Change the display name within the plugin.xml
// This needs to be here as otherwise the tests will throw errors.
@NotNull
@Override
public String getDisplayName() {
return "Incorrect delimiter";
}
@Override
public boolean runForWholeFile() {
return true;
}
@Nullable
@Override
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
if (!(file instanceof DotEnvFile)) {
return null;
}
return analyzeFile(file, manager, isOnTheFly).getResultsArray();
}
@NotNull
private ProblemsHolder analyzeFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
ProblemsHolder problemsHolder = new ProblemsHolder(manager, file, isOnTheFly);
PsiTreeUtil.findChildrenOfType(file, DotEnvKeyImpl.class).forEach(key -> {
if (key.getText().contains("-")) {
problemsHolder.registerProblem(key, "Expected: '_' Found: '-'", new ReplaceDelimiterQuickFix());
}
});
return problemsHolder;
}
private static class ReplaceDelimiterQuickFix implements LocalQuickFix {
@NotNull
@Override
public String getName() {
return "Replace delimiter";
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
try {
PsiElement psiElement = descriptor.getPsiElement();
PsiElement newPsiElement = DotEnvFactory.createFromText(project, DotEnvTypes.KEY,
psiElement.getText().replace("-","_")+"=dummy");
psiElement.replace(newPsiElement);
} catch (IncorrectOperationException e) {
Logger.getInstance(IncorrectDelimiterInspection.class).error(e);
}
}
@NotNull
public String getFamilyName() {
return getName();
}
}
}

View File

@@ -16,6 +16,13 @@ import ru.adelf.idea.dotenv.psi.DotEnvTypes;
import ru.adelf.idea.dotenv.psi.DotEnvValue;
public class SpaceInsideNonQuotedInspection extends LocalInspectionTool {
// Change the display name within the plugin.xml
// This needs to be here as otherwise the tests will throw errors.
@NotNull
@Override
public String getDisplayName() {
return "Space inside non-quoted value";
}
private AddQuotesQuickFix addQuotesQuickFix = new AddQuotesQuickFix();

View File

@@ -102,6 +102,22 @@
level="WARNING"
implementationClass="ru.adelf.idea.dotenv.inspections.SpaceInsideNonQuotedInspection"/>
<localInspection language="DotEnv"
groupName="DotEnv"
shortName="DotEnvExtraBlankLineInspection"
displayName="Extra blank line"
enabledByDefault="true"
level="WARNING"
implementationClass="ru.adelf.idea.dotenv.inspections.ExtraBlankLineInspection"/>
<localInspection language="DotEnv"
groupName="DotEnv"
shortName="DotEnvIncorrectDelimiterInspection"
displayName="Incorrect delimiter"
enabledByDefault="true"
level="WARNING"
implementationClass="ru.adelf.idea.dotenv.inspections.IncorrectDelimiterInspection"/>
<lang.syntaxHighlighterFactory language="DotEnv"
implementationClass="ru.adelf.idea.dotenv.DotEnvSyntaxHighlighterFactory"/>

View File

@@ -0,0 +1,5 @@
<html>
<body>
Reports extra blank lines in .env files.
</body>
</html>

View File

@@ -0,0 +1,5 @@
<html>
<body>
Reports incorrect delimiter in .env files ('-' instead of'_').
</body>
</html>

View File

@@ -0,0 +1,69 @@
package ru.adelf.idea.dotenv.tests.dotenv;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.InspectionProfileEntry;
import ru.adelf.idea.dotenv.inspections.DuplicateKeyInspection;
import ru.adelf.idea.dotenv.inspections.ExtraBlankLineInspection;
import ru.adelf.idea.dotenv.inspections.IncorrectDelimiterInspection;
import ru.adelf.idea.dotenv.inspections.SpaceInsideNonQuotedInspection;
import ru.adelf.idea.dotenv.tests.DotEnvLightCodeInsightFixtureTestCase;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class InspectionsTest extends DotEnvLightCodeInsightFixtureTestCase {
@Override
public void setUp() throws Exception {
super.setUp();
myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject("inspections.env"));
}
protected String getTestDataPath() {
return basePath + "dotenv/fixtures";
}
// Test for each Inspection
public void testDuplicateKey() {
doInspectionTest(new DuplicateKeyInspection(), Arrays.asList("DUPLICATE_KEY=test", "DUPLICATE_KEY=test2"));
}
public void testSpaceInsideNonQuoted() {
doInspectionTest(new SpaceInsideNonQuotedInspection(), Collections.singletonList("spaces without quotes"));
}
public void testExtraBlankLine() {
doInspectionTest(new ExtraBlankLineInspection(), Collections.singletonList("\n\n\n"));
}
public void testIncorrectDelimiterInspection() {
doInspectionTest(new IncorrectDelimiterInspection(), Collections.singletonList("INCORRECT-DELIMITER"));
}
// Every available quickfix from every inspection is getting applied
public void testQuickFixes() {
myFixture.enableInspections(new SpaceInsideNonQuotedInspection());
myFixture.enableInspections(new ExtraBlankLineInspection());
myFixture.enableInspections(new IncorrectDelimiterInspection());
myFixture.doHighlighting();
List<IntentionAction> intentionActions = myFixture.getAllQuickFixes();
intentionActions.forEach(intentionAction -> myFixture.launchAction(intentionAction));
myFixture.checkResultByFile("quickFix.env");
}
private void doInspectionTest(InspectionProfileEntry entry, List<String> expectedHighlightedText) {
myFixture.enableInspections(entry);
List<HighlightInfo> highlightInfoList = myFixture.doHighlighting();
List<String> actualHighlightedText = new ArrayList<>();
highlightInfoList.forEach( highlightInfo -> actualHighlightedText.add(highlightInfo.getText()));
assertEquals(expectedHighlightedText, actualHighlightedText);
}
}

View File

@@ -0,0 +1,11 @@
DUPLICATE_KEY=test
DUPLICATE_KEY=test2
SPACE_INSIDE_NON_QUOTED=spaces without quotes
# extra blank lines test START
# extra blank lines test END
INCORRECT-DELIMITER=test-test

View File

@@ -0,0 +1,10 @@
DUPLICATE_KEY=test
DUPLICATE_KEY=test2
SPACE_INSIDE_NON_QUOTED="spaces without quotes"
# extra blank lines test START
# extra blank lines test END
INCORRECT_DELIMITER=test-test