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
3 changes: 2 additions & 1 deletion .codacy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
# package name contains capital letter and such names are conventional.
---
exclude_paths:
- "eo-maven-plugin/src/test/java/org/eolang/maven/TranspileMojoIT.java"
- "eo-runtime/src/test/java/integration/JarIT.java"
- "eo-runtime/src/test/java/integration/EoMavenPlugin.java"
24 changes: 13 additions & 11 deletions eo-runtime/src/main/java/org/eolang/JavaPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
*/
package org.eolang;

import java.util.regex.Pattern;

/**
* Java path.
*
Expand All @@ -18,6 +20,15 @@
* @since 0.29
*/
final class JavaPath {
/**
* Phi pattern.
*/
private static final Pattern PHI = Pattern.compile("^Φ\\.?");

/**
* Dots pattern.
*/
private static final Pattern DOTS = Pattern.compile("(^|\\.)([^.]+)");

/**
* Object name in eolang notation.
Expand All @@ -34,17 +45,8 @@ final class JavaPath {

@Override
public String toString() {
if (!this.object.startsWith("Φ.")) {
throw new IllegalArgumentException(
String.format(
"Can't build path to .java file from FQN not started from '%s.'",
PhPackage.GLOBAL
)
);
}
return this.object
.substring(2)
.replaceAll("(^|\\.)([^.]+)", "$1EO$2")
return DOTS.matcher(JavaPath.PHI.matcher(this.object).replaceAll(""))
.replaceAll("$1EO$2")
.replace("$", "$EO")
.replace("-", "_");
}
Expand Down
89 changes: 50 additions & 39 deletions eo-runtime/src/main/java/org/eolang/PhPackage.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@

package org.eolang;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

Expand Down Expand Up @@ -69,18 +65,35 @@ public boolean hasRho() {

@Override
public Phi take(final String name) {
final String obj = String.join(".", this.pkg, name);
final String key = new JavaPath(obj).toString();
return this.objects.computeIfAbsent(
key,
k -> {
final Phi initialized = this.loadPhi(key, obj);
if (!(initialized instanceof PhPackage)) {
initialized.put(Attr.RHO, this);
}
return initialized;
final String fqn = String.join(".", this.pkg, name);
final Phi taken;
if (name.equals(Attr.RHO)) {
if (this.objects.containsKey(Attr.RHO)) {
taken = this.objects.get(Attr.RHO);
} else {
throw new ExUnset(
String.format(
"The %s attribute is absent in package object '%s'",
Attr.RHO, this.pkg
)
);
}
).copy();
} else if (this.objects.containsKey(fqn)) {
taken = this.objects.get(fqn).copy();
} else if (name.contains(".")) {
final String[] parts = name.split("\\.");
Phi next = this.take(parts[0]);
for (int idx = 1; idx < parts.length; ++idx) {
next = next.take(parts[idx]);
}
taken = next;
} else {
final Phi loaded = this.loadPhi(fqn);
loaded.put(Attr.RHO, this);
this.put(fqn, loaded);
taken = this.take(name);
}
return taken;
}

@Override
Expand All @@ -99,9 +112,7 @@ public void put(final int pos, final Phi object) {

@Override
public void put(final String name, final Phi object) {
throw new ExFailure(
"Can't #put(%s, %s) to package object \"%s\"", name, object, this.pkg
);
this.objects.put(name, object);
}

@Override
Expand All @@ -111,43 +122,43 @@ public byte[] delta() {

/**
* Load phi object by package name from ClassLoader.
* @param path Path to directory or .java file
* @param object Object FQN
* @param fqn FQN of the EO object
* @return Phi
*/
private Phi loadPhi(final String path, final String object) {
final Path pth = new File(
this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath()
).toPath().resolve(path.replace(".", File.separator));
final Phi phi;
if (Files.exists(pth) && Files.isDirectory(pth)) {
phi = new PhPackage(object);
} else {
final Path clazz = Paths.get(String.format("%s.class", pth));
if (!Files.exists(clazz) || Files.isDirectory(clazz)) {
throw new ExFailure(
String.format("Couldn't find object '%s'", object)
);
}
@SuppressWarnings("PMD.PreserveStackTrace")
private Phi loadPhi(final String fqn) {
final String target = new JavaPath(fqn).toString();
Phi loaded;
try {
Class.forName(String.format("%s.package-info", target));
loaded = new PhPackage(fqn);
} catch (final ClassNotFoundException pckg) {
try {
phi = (Phi) Class.forName(path)
loaded = (Phi) Class.forName(target)
.getConstructor()
.newInstance();
} catch (final ClassNotFoundException
| NoSuchMethodException
} catch (final ClassNotFoundException phi) {
throw new ExFailure(
String.format(
"Couldn't find object '%s' because there's no class or package '%s'",
fqn, target
),
phi
);
} catch (final NoSuchMethodException
| InvocationTargetException
| InstantiationException
| IllegalAccessException ex
) {
throw new ExFailure(
String.format(
"Couldn't build Java object \"%s\" in EO package \"%s\"",
path, this.pkg
target, this.pkg
),
ex
);
}
}
return phi;
return loaded;
}
}
48 changes: 48 additions & 0 deletions eo-runtime/src/test/java/integration/EoMavenPlugin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com
* SPDX-License-Identifier: MIT
*/
package integration;

import com.jcabi.manifests.Manifests;
import com.yegor256.farea.Farea;
import com.yegor256.farea.Plugin;
import java.io.IOException;

/**
* The eo-maven-plugin appended to {@link Farea}.
* @since 0.54
*/
final class EoMavenPlugin {
/**
* Farea.
*/
private final Farea farea;

/**
* Ctor.
* @param farea Farea
*/
EoMavenPlugin(final Farea farea) {
this.farea = farea;
}

/**
* Append eo-maven-plugin to farea build.
* @return Appended eo-maven-plugin
* @throws IOException If fails to append
*/
Plugin appended() throws IOException {
return this.farea
.build()
.plugins()
.append(
"org.eolang",
"eo-maven-plugin",
System.getProperty(
"eo.version",
Manifests.read("EO-Version")
)
);
}
}
86 changes: 86 additions & 0 deletions eo-runtime/src/test/java/integration/JarIT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2016-2025 Objectionary.com
* SPDX-License-Identifier: MIT
*/
package integration;

import com.jcabi.manifests.Manifests;
import com.yegor256.Jaxec;
import com.yegor256.MayBeSlow;
import com.yegor256.Mktmp;
import com.yegor256.MktmpResolver;
import com.yegor256.WeAreOnline;
import com.yegor256.farea.Farea;
import com.yegor256.farea.RequisiteMatcher;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

/**
* Integration test that runs simple EO program from packaged jar.
* @since 0.54
*/
@SuppressWarnings({"JTCOP.RuleAllTestsHaveProductionClass", "JTCOP.RuleNotContainsTestWord"})
@ExtendWith(MktmpResolver.class)
final class JarIT {
@Test
@ExtendWith(WeAreOnline.class)
@ExtendWith(MayBeSlow.class)
void runsProgramFromJar(final @Mktmp Path temp) throws IOException {
new Farea(temp).together(
f -> {
f.properties()
.set("project.build.sourceEncoding", StandardCharsets.UTF_8.name())
.set("project.reporting.outputEncoding", StandardCharsets.UTF_8.name());
f.files().file("src/main").save(
Paths.get(System.getProperty("user.dir")).resolve("src/main")
);
f.files()
.file("src/main/eo/simple.eo")
.write(
"QQ.io.stdout \"Hello, world!\" > simple\n".getBytes(StandardCharsets.UTF_8)
);
f.dependencies()
.append(
"org.eolang",
"eo-runtime",
System.getProperty(
"eo.version",
Manifests.read("EO-Version")
)
);
new EoMavenPlugin(f)
.appended()
.execution("compile")
.phase("generate-sources")
.goals("register", "compile", "transpile")
.configuration()
.set("failOnWarning", Boolean.FALSE.toString())
.set("skipLinting", Boolean.TRUE.toString());
f.exec("clean", "compile", "jar:jar");
MatcherAssert.assertThat(
"Project must be successfully built and packaged into jar",
f.log(),
RequisiteMatcher.SUCCESS
);
MatcherAssert.assertThat(
"Simple program must be successfully executed from jar",
new Jaxec(
"java", "-cp", "test-0.0.0.jar",
"-Dfile.encoding=UTF-8", "-Xss64M", "-Xms64M",
"org.eolang.Main", "simple"
).withHome(temp.resolve("target")).exec().stdout(),
Matchers.allOf(
Matchers.containsString("Hello, world!"),
Matchers.containsString("[0x01] = true")
)
);
}
);
}
}
24 changes: 4 additions & 20 deletions eo-runtime/src/test/java/integration/PhiUnphiIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,8 @@ void runsTestsAfterPhiAndUnphi(final @Mktmp Path temp) throws IOException {
"Saxon-HE",
"12.4"
);
f.build()
.plugins()
.append(
"org.eolang",
"eo-maven-plugin",
System.getProperty(
"eo.version",
Manifests.read("EO-Version")
)
)
new EoMavenPlugin(f)
.appended()
.execution("phi-unphi")
.phase("process-sources")
.goals(
Expand Down Expand Up @@ -135,16 +127,8 @@ void runsTestsAfterPhiAndUnphi(final @Mktmp Path temp) throws IOException {
.set("skipLinting", Boolean.TRUE.toString())
.set("ignoreRuntime", Boolean.TRUE.toString())
.set("placeBinariesThatHaveSources", Boolean.TRUE.toString());
f.build()
.plugins()
.append(
"org.eolang",
"eo-maven-plugin",
System.getProperty(
"eo.version",
"1.0-SNAPSHOT"
)
)
new EoMavenPlugin(f)
.appended()
.execution("tests")
.phase("generate-test-sources")
.goals(
Expand Down
20 changes: 2 additions & 18 deletions eo-runtime/src/test/java/integration/SnippetIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,6 @@

/**
* Integration test for simple snippets.
*
* <p>This test will/may fail if you change something in {@code to-java.xsl}
* or some other place where Java sources are generated. This happens
* because this test relies on {@code eo-runtime.jar}, which it finds in Maven
* Central. Thus, when changes are made, it is recommended to disable this test.
* Then, when new {@code eo-runtime.jar} is
* released to Maven Central, you enable this test again.</p>
*
* @since 0.1
*/
@SuppressWarnings({"JTCOP.RuleAllTestsHaveProductionClass", "JTCOP.RuleNotContainsTestWord"})
Expand Down Expand Up @@ -84,16 +76,8 @@ void runsAllSnippets(final String yml, final @Mktmp Path temp) throws IOExceptio
f.build()
.properties()
.set("directory", target);
f.build()
.plugins()
.append(
"org.eolang",
"eo-maven-plugin",
System.getProperty(
"eo.version",
Manifests.read("EO-Version")
)
)
new EoMavenPlugin(f)
.appended()
.execution("compile")
.phase("generate-sources")
.goals("register", "compile", "transpile")
Expand Down
Loading