diff --git a/gherkin-checks/src/main/java/org/sonar/gherkin/checks/DuplicatedStepsCheck.java b/gherkin-checks/src/main/java/org/sonar/gherkin/checks/DuplicatedStepsCheck.java index a6e08b9..625739b 100644 --- a/gherkin-checks/src/main/java/org/sonar/gherkin/checks/DuplicatedStepsCheck.java +++ b/gherkin-checks/src/main/java/org/sonar/gherkin/checks/DuplicatedStepsCheck.java @@ -19,6 +19,7 @@ */ package org.sonar.gherkin.checks; +import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import org.sonar.check.Priority; import org.sonar.check.Rule; @@ -28,9 +29,11 @@ import org.sonar.squidbridge.annotations.ActivatedByDefault; import org.sonar.squidbridge.annotations.SqaleConstantRemediation; +import javax.annotation.Nullable; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; @Rule( key = "duplicated-steps", @@ -47,14 +50,14 @@ public class DuplicatedStepsCheck extends DoubleDispatchVisitorCheck { public void visitFeature(FeatureTree tree) { backgroundStepsBySentence.clear(); if (tree.background() != null) { - backgroundStepsBySentence = buildStepsBySentenceMap(tree.background().steps()); + backgroundStepsBySentence = getStepsBySentence(tree.background().steps()); } super.visitFeature(tree); } @Override public void visitBackground(BackgroundTree tree) { - checkForDuplicatedStepsInBackground(tree); + checkForDuplicatedStepsInBackground(); } @Override @@ -67,34 +70,25 @@ public void visitScenarioOutline(ScenarioOutlineTree tree) { checkForDuplicatedStepsInScenario(tree); } - private void checkForDuplicatedStepsInBackground(BackgroundTree tree) { - for (Map.Entry> entry : buildStepsBySentenceMap(tree.steps()).entrySet()) { - if (entry.getValue().size() > 1) { - PreciseIssue issue = addPreciseIssue(entry.getValue().get(0), "Remove this duplicated step."); - for (int i = 1; i < entry.getValue().size(); i++) { - issue.secondary(entry.getValue().get(i), "Duplicate"); - } - } - } + private void checkForDuplicatedStepsInBackground() { + backgroundStepsBySentence + .entrySet() + .stream() + .filter(sentence -> sentence.getValue().size() > 1) + .forEach(sentence -> createIssue(sentence.getValue())); } private void checkForDuplicatedStepsInScenario(BasicScenarioTree tree) { - for (Map.Entry> entry : buildStepsBySentenceMap(tree.steps()).entrySet()) { - if (entry.getValue().size() > 1 || backgroundStepsBySentence.keySet().contains(entry.getKey())) { - PreciseIssue issue = addPreciseIssue(entry.getValue().get(0), "Remove this duplicated step."); - for (int i = 1; i < entry.getValue().size(); i++) { - issue.secondary(entry.getValue().get(i), "Duplicate"); - } - if (backgroundStepsBySentence.get(entry.getKey()) != null) { - for (int i = 0; i < backgroundStepsBySentence.get(entry.getKey()).size(); i++) { - issue.secondary(backgroundStepsBySentence.get(entry.getKey()).get(i), "Duplicate"); - } - } - } - } + getStepsBySentence(tree.steps()) + .entrySet() + .stream() + .filter(sentence -> sentence.getValue().size() > 1 || backgroundStepsBySentence.keySet().contains(sentence.getKey())) + .forEach(sentence -> createIssue( + sentence.getValue(), + backgroundStepsBySentence.get(sentence.getKey()))); } - private Map> buildStepsBySentenceMap(List steps) { + private Map> getStepsBySentence(List steps) { Map> stepsBySentence = new HashMap<>(); for (StepTree step : steps) { @@ -108,4 +102,23 @@ private Map> buildStepsBySentenceMap(List steps return stepsBySentence; } + private void createIssue(List duplicatedSteps) { + createIssue(duplicatedSteps, null); + } + + private void createIssue(List duplicatedSteps, @Nullable List duplicatedStepsInBackground) { + Preconditions.checkElementIndex(0, duplicatedSteps.size()); + + PreciseIssue issue = addPreciseIssue(duplicatedSteps.get(0), "Remove this duplicated step."); + addSecondaryLocation(issue, duplicatedSteps.stream().skip(1).collect(Collectors.toList())); + + if (duplicatedStepsInBackground != null) { + addSecondaryLocation(issue, duplicatedStepsInBackground); + } + } + + private void addSecondaryLocation(PreciseIssue issue, List secondaryLocations) { + secondaryLocations.forEach(s -> issue.secondary(s, "Duplicate")); + } + } diff --git a/gherkin-checks/src/main/java/org/sonar/gherkin/checks/SpellingCheck.java b/gherkin-checks/src/main/java/org/sonar/gherkin/checks/SpellingCheck.java index 8113d2a..a118a00 100644 --- a/gherkin-checks/src/main/java/org/sonar/gherkin/checks/SpellingCheck.java +++ b/gherkin-checks/src/main/java/org/sonar/gherkin/checks/SpellingCheck.java @@ -132,7 +132,7 @@ private JLanguageTool createLanguageTool() { JLanguageTool jLanguageTool = new JLanguageTool(dictionary); - Arrays.stream(rulesToIgnore.split(",")).forEach(r -> jLanguageTool.disableRule(r)); + Arrays.stream(rulesToIgnore.split(",")).forEach(jLanguageTool::disableRule); jLanguageTool.getAllActiveRules() .stream() diff --git a/gherkin-frontend/src/main/java/org/sonar/gherkin/parser/GherkinParser.java b/gherkin-frontend/src/main/java/org/sonar/gherkin/parser/GherkinParser.java index 3af3750..b18c447 100644 --- a/gherkin-frontend/src/main/java/org/sonar/gherkin/parser/GherkinParser.java +++ b/gherkin-frontend/src/main/java/org/sonar/gherkin/parser/GherkinParser.java @@ -27,6 +27,7 @@ import java.io.File; import java.nio.charset.Charset; +import java.util.Objects; public class GherkinParser extends ActionParser { @@ -44,7 +45,7 @@ private static Tree createParentLink(Tree parent) { if (!parent.isLeaf()) { Lists.newArrayList(parent.childrenIterator()) .stream() - .filter(nextTree -> nextTree != null) + .filter(Objects::nonNull) .forEach(nextTree -> { nextTree.setParent(parent); createParentLink(nextTree);