Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion eo-maven-plugin/src/main/java/org/eolang/maven/EoSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.function.UnaryOperator;
import org.cactoos.Input;
import org.cactoos.io.InputOf;
import org.eolang.parser.Canonical;
import org.eolang.parser.EoSyntax;
import org.eolang.parser.OnDefault;
import org.eolang.parser.OnDetailed;
Expand All @@ -37,6 +39,11 @@ final class EoSource {
*/
private final Input input;

/**
* Transform that parses EO into XMIR.
*/
private final UnaryOperator<XML> transform;

/**
* Ctor.
* @param identifier Object identifier
Expand All @@ -52,8 +59,29 @@ final class EoSource {
* @param input Object source code
*/
EoSource(final String identifier, final Input input) {
this(identifier, input, new Canonical());
}

/**
* Ctor.
* @param identifier Object identifier
* @param source Path to the source file
* @param transform Transform that parses EO into XMIR
*/
EoSource(final String identifier, final Path source, final UnaryOperator<XML> transform) {
this(identifier, new InputOf(source), transform);
}

/**
* Ctor.
* @param identifier Object identifier
* @param input Object source code
* @param transform Transform that parses EO into XMIR
*/
EoSource(final String identifier, final Input input, final UnaryOperator<XML> transform) {
this.identifier = identifier;
this.input = input;
this.transform = transform;
}

/**
Expand All @@ -62,7 +90,7 @@ final class EoSource {
* @throws IOException If fails
*/
Xmir parsed() throws IOException {
final XML xmir = new EoSyntax(this.input).parsed();
final XML xmir = new EoSyntax(this.input, this.transform).parsed();
final List<String> errors = new ArrayList<>(0);
final Node document = xmir.inner();
final String name = new OnDetailed(
Expand Down
61 changes: 51 additions & 10 deletions eo-maven-plugin/src/main/java/org/eolang/maven/Parsing.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,23 @@
import com.github.lombrozo.xnav.Filter;
import com.github.lombrozo.xnav.Xnav;
import com.jcabi.log.Logger;
import com.jcabi.xml.XML;
import com.jcabi.xml.XMLDocument;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import org.cactoos.bytes.Sha256DigestOf;
import org.cactoos.io.InputOf;
import org.cactoos.iterable.Filtered;
import org.cactoos.text.HexOf;
import org.cactoos.text.TextOf;
import org.cactoos.text.UncheckedText;
import org.eolang.parser.Canonical;
import org.w3c.dom.Node;

/**
Expand Down Expand Up @@ -115,10 +122,19 @@ final class Parsing implements Step {
@Override
public void exec() {
final Collection<TjForeign> sources = this.tojos.withSources();
final int total = new Threaded<>(
new Filtered<>(TjForeign::notParsed, sources),
this::parsed
).total();
final String objects = sources.stream()
.map(TjForeign::identifier)
.filter(id -> id.contains("."))
.distinct()
.sorted()
.collect(Collectors.joining(" "));
final int total = this.parsed(
sources,
new Canonical(objects),
new UncheckedText(
new HexOf(new Sha256DigestOf(new InputOf(objects)))
).asString()
);
if (0 == total) {
if (sources.isEmpty()) {
Logger.info(
Expand All @@ -140,13 +156,35 @@ public void exec() {
}
}

/**
* Parse all the given sources to XMIRs, concurrently.
* @param sources The sources to parse
* @param pipeline The canonical parsing transform to apply
* @param digest Digest of the set of known objects (part of the cache key)
* @return Amount of parsed tojos
*/
private int parsed(
final Collection<TjForeign> sources,
final UnaryOperator<XML> pipeline,
final String digest
) {
return new Threaded<>(
new Filtered<>(TjForeign::notParsed, sources),
tojo -> this.parsed(tojo, pipeline, digest)
).total();
}

/**
* Parse EO file to XML.
* @param tojo The tojo
* @param pipeline The canonical parsing transform to apply
* @param digest Digest of the set of known objects (part of the cache key)
* @return Amount of parsed tojos
* @throws Exception If fails
*/
private int parsed(final TjForeign tojo) throws Exception {
private int parsed(
final TjForeign tojo, final UnaryOperator<XML> pipeline, final String digest
) throws Exception {
final Path source = tojo.source();
final String name = tojo.identifier();
final Path base = this.targetDir.resolve(Parsing.DIR);
Expand All @@ -157,18 +195,18 @@ private int parsed(final TjForeign tojo) throws Exception {
new Cache(
new CachePath(
this.cacheDir.resolve(Parsing.CACHE),
this.version,
String.format("%s-%s", this.version, digest),
new TojoHash(tojo).get()
),
src -> {
final Node node = this.parsed(src, name);
final Node node = this.parsed(src, name, pipeline);
refs.add(node);
return new XMLDocument(node).toString();
}
)
).apply(source, target, base.relativize(target));
} else {
final Node node = this.parsed(source, name);
final Node node = this.parsed(source, name, pipeline);
new Saved(new XMLDocument(node).toString(), target).value();
refs.add(node);
}
Expand Down Expand Up @@ -198,11 +236,14 @@ private int parsed(final TjForeign tojo) throws Exception {
* Source parsed to {@link Node}.
* @param source Relative source path
* @param identifier Name of the EO object as tojo identifier
* @param pipeline The canonical parsing transform to apply
* @return Parsed EO object as {@link Node}
* @throws IOException If fails to parse
*/
private Node parsed(final Path source, final String identifier) throws IOException {
final EoSource.Xmir xmir = new EoSource(identifier, source).parsed();
private Node parsed(
final Path source, final String identifier, final UnaryOperator<XML> pipeline
) throws IOException {
final EoSource.Xmir xmir = new EoSource(identifier, source, pipeline).parsed();
Logger.debug(
Parsing.class,
"Parsed program '%s' from %[file]s:%n %s",
Expand Down
83 changes: 82 additions & 1 deletion eo-maven-plugin/src/test/java/org/eolang/maven/MjParseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
import java.util.Map;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.cactoos.bytes.Sha256DigestOf;
import org.cactoos.io.InputOf;
import org.cactoos.io.ResourceOf;
import org.cactoos.text.HexOf;
import org.cactoos.text.TextOf;
import org.cactoos.text.UncheckedText;
import org.hamcrest.MatcherAssert;
Expand Down Expand Up @@ -91,7 +94,7 @@ void parsesWithCache(@Mktmp final Path temp) throws Exception {
final Path target = new Place("foo.x.main").make(base, MjAssemble.XMIR);
new Cache(
cache.resolve(Parsing.CACHE)
.resolve(FakeMaven.pluginVersion())
.resolve(MjParseTest.cacheVersion(maven.programTojo().identifier()))
.resolve(hash.value()),
src -> expected
).apply(maven.programTojo().source(), target, base.relativize(target));
Expand Down Expand Up @@ -131,6 +134,66 @@ void doesNotCrashesOnError(@Mktmp final Path temp) throws Exception {
);
}

@Test
void homesBareReferenceToSamePackageObject(@Mktmp final Path temp) throws IOException {
final FakeMaven maven = new FakeMaven(temp);
maven.withProgram(
String.join(
System.lineSeparator(),
"+package foo",
"",
"[] > bar",
" 42 > @"
),
"foo.bar",
"foo/bar.eo"
).withProgram(
String.join(
System.lineSeparator(),
"+package foo",
"",
"[] > app",
" bar > @"
),
"foo.app",
"foo/app.eo"
);
MatcherAssert.assertThat(
"bare reference 'bar' must be resolved into the same package as 'Φ.foo.bar'",
new XMLDocument(
maven.execute(new FakeMaven.Parse()).result().get(
String.format("target/%s/foo/app.%s", Parsing.DIR, MjAssemble.XMIR)
)
),
XhtmlMatchers.hasXPath("//o[@base='Φ.foo.bar']")
);
}

@Test
void keepsBareGlobalReferenceAtRoot(@Mktmp final Path temp) throws IOException {
final FakeMaven maven = new FakeMaven(temp);
maven.withProgram(
String.join(
System.lineSeparator(),
"+package foo",
"",
"[] > app",
" bar > @"
),
"foo.app",
"foo/app.eo"
);
MatcherAssert.assertThat(
"bare reference 'bar' must stay at the root when no 'Φ.foo.bar' object exists",
new XMLDocument(
maven.execute(new FakeMaven.Parse()).result().get(
String.format("target/%s/foo/app.%s", Parsing.DIR, MjAssemble.XMIR)
)
),
XhtmlMatchers.hasXPath("//o[@base='Φ.bar']")
);
}

@Test
void crashesIfWrongPackage(@Mktmp final Path temp) throws IOException {
new FakeMaven(temp).withProgram(
Expand Down Expand Up @@ -278,6 +341,24 @@ void parsesWithTargetCache(@Mktmp final Path temp) throws IOException {
);
}

/**
* The parse cache version segment for a program with a single object.
* It mirrors what {@link Parsing} computes: the plugin version plus a
* SHA-256 digest of the qualified names of the local package objects
* (here, the identifier of the only object).
* @param identifier The tojo identifier of the only registered object
* @return The version segment used as part of the parse cache path
*/
private static String cacheVersion(final String identifier) {
return String.format(
"%s-%s",
FakeMaven.pluginVersion(),
new UncheckedText(
new HexOf(new Sha256DigestOf(new InputOf(identifier)))
).asString()
);
}

/**
* The mojo that does nothing, but executes infinitely.
* @since 0.29
Expand Down
Loading
Loading