diff --git a/src/test/java/org/eolang/lints/LtByXslTest.java b/src/test/java/org/eolang/lints/LtByXslTest.java index 144bef92c..639d7c461 100644 --- a/src/test/java/org/eolang/lints/LtByXslTest.java +++ b/src/test/java/org/eolang/lints/LtByXslTest.java @@ -108,6 +108,10 @@ void lintsInMultipleThreads() { @ParameterizedTest @ClasspathSource(value = "org/eolang/lints/packs/single/", glob = "**.yaml") void testsAllLintsByEo(final String yaml, final String pack) { + org.junit.jupiter.api.Assumptions.assumeTrue( + !((Map) new org.yaml.snakeyaml.Yaml().load(yaml)).containsKey("lint"), + String.format("Pack '%s' is a Java lint pack", pack) + ); MatcherAssert.assertThat( String.format( "Pack '%s' doesn't tell the story as expected", @@ -125,6 +129,32 @@ void testsAllLintsByEo(final String yaml, final String pack) { ); } + @SuppressWarnings("JTCOP.RuleNotContainsTestWord") + @Execution(ExecutionMode.CONCURRENT) + @ParameterizedTest + @ClasspathSource(value = "org/eolang/lints/packs/single/", glob = "**.yaml") + void testsAllLintsByLintName(final String yaml, final String pack) { + org.junit.jupiter.api.Assumptions.assumeTrue( + ((Map) new org.yaml.snakeyaml.Yaml().load(yaml)).containsKey("lint"), + String.format("Pack '%s' has no lint key", pack) + ); + MatcherAssert.assertThat( + String.format( + "Pack '%s' doesn't tell the story as expected", + pack + ), + new fixtures.XtDefects( + new XtSticky( + new XtLint( + yaml, + eo -> new EoProgram(pack, new InputOf(eo)).parse() + ) + ) + ), + new XtoryMatcher(new DefectsMatcher()) + ); + } + @Test void returnsMotive() throws Exception { MatcherAssert.assertThat( @@ -480,22 +510,31 @@ private static Predicate yamls() { */ @SuppressWarnings("StreamResourceLeak") private static boolean hasMatchingXsl(final Path yaml) { + final boolean result; try { - return Files.walk(Paths.get("src/main/resources/org/eolang/lints")) - .filter(Files::isRegularFile) - .filter(path -> path.toString().endsWith(".xsl")) - .map(path -> path.getParent().getFileName().toString()).anyMatch( - group -> Files.exists( - Paths.get("src/main/resources/org/eolang/lints/").resolve(group).resolve( - String.format( - "%s.xsl", - yaml.getParent().getFileName().toString() - ) + if (((Map) new org.yaml.snakeyaml.Yaml().load( + new String(Files.readAllBytes(yaml), java.nio.charset.StandardCharsets.UTF_8) + )).containsKey("lint")) { + result = true; + } else { + result = Files.walk(Paths.get("src/main/resources/org/eolang/lints")) + .filter(Files::isRegularFile) + .filter(path -> path.toString().endsWith(".xsl")) + .map(path -> path.getParent().getFileName().toString()).anyMatch( + group -> Files.exists( + Paths.get("src/main/resources/org/eolang/lints/") + .resolve(group).resolve( + String.format( + "%s.xsl", + yaml.getParent().getFileName().toString() + ) + ) ) - ) - ); + ); + } } catch (final IOException ex) { throw new IllegalStateException(ex); } + return result; } } diff --git a/src/test/java/org/eolang/lints/XtLint.java b/src/test/java/org/eolang/lints/XtLint.java new file mode 100644 index 000000000..4c0ab79c9 --- /dev/null +++ b/src/test/java/org/eolang/lints/XtLint.java @@ -0,0 +1,123 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com + * SPDX-License-Identifier: MIT + */ +package org.eolang.lints; + +import com.jcabi.xml.XML; +import com.yegor256.xsline.Shift; +import com.yegor256.xsline.Xsline; +import java.io.IOException; +import java.util.Collection; +import java.util.Map; +import org.eolang.xax.Xtory; +import org.xembly.Directives; +import org.xembly.Xembler; + +/** + * A story that runs a Java-implemented lint by its name. + * Reads the {@code lint} key from the pack YAML and applies + * the resolved {@link Lint} to the input, producing a + * {@code } document. + * @since 1.0 + */ +public final class XtLint implements Xtory { + + /** + * Original story. + */ + private final Xtory origin; + + /** + * Ctor. + * @param yaml YAML pack + * @param parser Parser + */ + public XtLint(final String yaml, final Xtory.Parser parser) { + this(new org.eolang.xax.XtYaml(yaml, parser)); + } + + /** + * Ctor. + * @param origin Original story + */ + private XtLint(final Xtory origin) { + this.origin = origin; + } + + @Override + public Map map() { + return this.origin.map(); + } + + @Override + public XML before() { + return this.origin.before(); + } + + @Override + public XML after() { + return this.xsline().pass(this.before()); + } + + @Override + public Xsline xsline() { + return new Xsline( + new Shift() { + @Override + public String uid() { + return XtLint.this.name(); + } + + @Override + public XML apply(final int position, final XML xml) { + return XtLint.this.defects(xml); + } + } + ); + } + + @Override + public Collection asserts() { + return this.origin.asserts(); + } + + /** + * Lint name from the YAML map. + * @return Lint name + */ + private String name() { + return String.valueOf(this.origin.map().get("lint")); + } + + /** + * Run the lint and serialize defects into XML. + * @param xml Input XMIR + * @return Defects document + */ + private XML defects(final XML xml) { + final Directives dirs = new Directives().add("defects"); + try { + for (final Lint lint : new PkMono()) { + if (lint.name().equals(this.name())) { + for (final Defect defect : lint.defects(xml)) { + dirs.add("defect") + .attr("line", defect.line()) + .attr("severity", defect.severity().mnemo()) + .set(defect.text()) + .up(); + } + break; + } + } + } catch (final IOException ex) { + throw new IllegalStateException( + String.format("Failed to run lint %s", this.name()), + ex + ); + } + return new com.jcabi.xml.XMLDocument( + new Xembler(dirs).xmlQuietly() + ); + } +} diff --git a/src/test/resources/org/eolang/lints/packs/single/ascii-only/catches-cyrillic-comment.yaml b/src/test/resources/org/eolang/lints/packs/single/ascii-only/catches-cyrillic-comment.yaml new file mode 100644 index 000000000..5d0bcf528 --- /dev/null +++ b/src/test/resources/org/eolang/lints/packs/single/ascii-only/catches-cyrillic-comment.yaml @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com +# SPDX-License-Identifier: MIT +--- +lint: ascii-only +asserts: + - /defects[count(defect[@severity='warning'])=1] +document: | + + + привет + + diff --git a/src/test/resources/org/eolang/lints/packs/single/incorrect-unlint/catches-unknown-lint.yaml b/src/test/resources/org/eolang/lints/packs/single/incorrect-unlint/catches-unknown-lint.yaml new file mode 100644 index 000000000..abbd3d665 --- /dev/null +++ b/src/test/resources/org/eolang/lints/packs/single/incorrect-unlint/catches-unknown-lint.yaml @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com +# SPDX-License-Identifier: MIT +--- +lint: incorrect-unlint +asserts: + - /defects[count(defect[@severity='error'])=1] +document: | + + + + unlint + non-existent-lint-name:5 + + + + diff --git a/src/test/resources/org/eolang/lints/packs/single/reserved-name/allows-custom-name.yaml b/src/test/resources/org/eolang/lints/packs/single/reserved-name/allows-custom-name.yaml new file mode 100644 index 000000000..380aa342e --- /dev/null +++ b/src/test/resources/org/eolang/lints/packs/single/reserved-name/allows-custom-name.yaml @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com +# SPDX-License-Identifier: MIT +--- +lint: reserved-name +asserts: + - /defects[count(defect)=0] +document: | + + + + + diff --git a/src/test/resources/org/eolang/lints/packs/single/syntax-version/allows-older-syntax.yaml b/src/test/resources/org/eolang/lints/packs/single/syntax-version/allows-older-syntax.yaml new file mode 100644 index 000000000..12b93f246 --- /dev/null +++ b/src/test/resources/org/eolang/lints/packs/single/syntax-version/allows-older-syntax.yaml @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com +# SPDX-License-Identifier: MIT +--- +lint: syntax-version +asserts: + - /defects[count(defect)=0] +document: | + + + + syntax + 0.0.1 + + + + diff --git a/src/test/resources/org/eolang/lints/packs/single/syntax-version/catches-newer-syntax.yaml b/src/test/resources/org/eolang/lints/packs/single/syntax-version/catches-newer-syntax.yaml new file mode 100644 index 000000000..873e566d7 --- /dev/null +++ b/src/test/resources/org/eolang/lints/packs/single/syntax-version/catches-newer-syntax.yaml @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com +# SPDX-License-Identifier: MIT +--- +lint: syntax-version +asserts: + - /defects[count(defect[@severity='error'])=1] +document: | + + + + syntax + 999.0.0 + + + +