Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 39 additions & 16 deletions src/main/java/org/eolang/lints/LtUnlintNonExistingDefect.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
import com.github.lombrozo.xnav.Xnav;
import com.jcabi.xml.XML;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.cactoos.list.ListOf;
Expand Down Expand Up @@ -55,10 +57,18 @@ public String name() {

@Override
public Collection<Defect> defects(final XML xmir) throws IOException {
return new Xnav(xmir.inner()).path("/object/metas/meta[head='unlint']/tail")
final List<String> unlints = new Xnav(xmir.inner())
.path("/object/metas/meta[head='unlint']/tail")
.map(xnav -> xnav.text().get())
.distinct()
.filter(new DefectMissing(this.existingDefects(xmir), this.excluded)::apply).flatMap(
.collect(Collectors.toList());
final Collection<Defect> messages;
if (unlints.isEmpty()) {
messages = new ArrayList<>(0);
} else {
messages = unlints.stream().filter(
new DefectMissing(this.existing(unlints, xmir), this.excluded)::apply
).flatMap(
unlint -> new Xnav(xmir.inner()).path(
String.format(
"object/metas/meta[head='unlint' and tail=%s]/@line",
Expand All @@ -76,6 +86,8 @@ public Collection<Defect> defects(final XML xmir) throws IOException {
)
)
).collect(Collectors.toList());
}
return messages;
}

@Override
Expand Down Expand Up @@ -105,20 +117,31 @@ private static String quoted(final String value) {
return result;
}

private Map<String, List<Integer>> existingDefects(final XML xmir) {
return StreamSupport.stream(this.lints.spliterator(), false).flatMap(
lint -> {
try {
return lint.defects(xmir).stream();
} catch (final IOException exception) {
throw new IllegalStateException(exception);
/**
* Build a map of existing defects, checking only lints referenced by
* <code>+unlint</code> metas.
* @param unlints Tails of all <code>+unlint</code> metas in the document
* @param xmir The XMIR document
* @return Existing defects grouped by rule and line
*/
private Map<String, List<Integer>> existing(final List<String> unlints, final XML xmir) {
final Set<String> names = unlints.stream()
.map(unlint -> unlint.split(":", -1)[0])
.collect(Collectors.toSet());
return StreamSupport.stream(this.lints.spliterator(), false)
.filter(lint -> names.contains(lint.name())).flatMap(
lint -> {
try {
return lint.defects(xmir).stream();
} catch (final IOException exception) {
throw new IllegalStateException(exception);
}
}
}
).collect(
Collectors.groupingBy(
Defect::rule,
Collectors.mapping(Defect::line, Collectors.toList())
)
);
).collect(
Collectors.groupingBy(
Defect::rule,
Collectors.mapping(Defect::line, Collectors.toList())
)
);
}
}
60 changes: 60 additions & 0 deletions src/test/java/org/eolang/lints/LtUnlintNonExistingDefectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
*/
package org.eolang.lints;

import com.jcabi.xml.XML;
import fixtures.EoProgram;
import java.io.IOException;
import java.util.Collection;
import java.util.stream.Collectors;
import org.cactoos.list.ListOf;
import org.hamcrest.MatcherAssert;
Expand Down Expand Up @@ -187,4 +189,62 @@ void catchesUnlintWithApostrophe() throws IOException {
Matchers.iterableWithSize(1)
);
}

@Test
void doesNotRunLintsWithoutUnlints() throws IOException {
MatcherAssert.assertThat(
"Lints should not be executed when there are no +unlint metas",
new LtUnlintNonExistingDefect(
new ListOf<>(new LtUnlintNonExistingDefectTest.Boom()),
new ListOf<>()
).defects(
new EoProgram("org/eolang/lints/non-ascii-bar.eo").parse()
),
Matchers.emptyIterable()
);
}

@Test
void doesNotInvokeUnreferencedLint() throws IOException {
MatcherAssert.assertThat(
"Only the referenced lint should be executed",
new LtUnlintNonExistingDefect(
new ListOf<>(
new LtAsciiOnly(),
new LtUnlintNonExistingDefectTest.Boom()
),
new ListOf<>()
).defects(
new EoProgram("org/eolang/lints/unlint-ascii-only-no-defect.eo").parse()
),
Matchers.hasSize(Matchers.greaterThan(0))
);
}

/**
* Fake lint that explodes when invoked.
* @since 0.0.40
*/
private static final class Boom implements Lint {

@Override
public String name() {
return "boom";
}

@Override
public Collection<Defect> defects(final XML xmir) {
throw new IllegalStateException("this lint must not be executed");
}

@Override
public String motive() {
return "";
}

@Override
public Fix fix() {
return new FxEmpty();
}
}
}
Loading