<?xml version="1.0" encoding="UTF-8"?>
<!--
* SPDX-FileCopyrightText: Copyright (c) 2016-2026 Objectionary.com
* SPDX-License-Identifier: MIT
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.eolang</groupId>
    <artifactId>eo-parent</artifactId>
    <version>0.63.2</version>
  </parent>
  <artifactId>eo-runtime</artifactId>
  <packaging>jar</packaging>
  <name>eo-runtime</name>
  <description>EO runtime library</description>
  <properties>
    <!-- This is required for later correct replacement of argline -->
    <argLine/>
    <!--
    How many seconds a single test may run before Deadline skips it. Raise
    it on a box that has all the time in the world, so that a slow test
    runs to its end instead of being skipped. The "transpile" goal reads the
    same property and writes it into the @Timeout of every test it makes out
    of an .eo file, while the hand-written tests get it from surefire below.
    -->
    <eo.deadline>1</eo.deadline>
    <!--
    How much memory a single test may allocate before Maxmem terminates it
    and reports it as skipped. The suffixes of -Xmx are understood: "2G",
    "512M", "65536K", or plain bytes. Empty, or zero, means no limit at all
    and no watching either: a box with memory to spare should run every
    test to its end. The value here sits above the band an ordinary test
    occupies — a directory walk passes about 300M through the allocator
    without ever holding much — so that the guard fires on a runaway test
    rather than on the population (#8341). It binds one test, while tests
    run as wide as the box has cores, so a job raising it from the command
    line must keep the value times the workers under -Xmx. The "transpile"
    goal reads the same property and writes it into the @Budget of every
    test it makes out of an .eo file, which wins over the system property.
    -->
    <eo.maxmem>1G</eo.maxmem>
  </properties>
  <dependencies>
    <dependency>
      <!--
      This dependency is required by the javadoc plugin. In the eo-runtime,
      we use classes from this JAR, but can't have it as a normal dependency.
      That's why the scope is "provided" here: it won't become a transitive
      one, but at the same time will satisfy javadoc plugin.
      -->
      <groupId>net.java.dev.jna</groupId>
      <artifactId>jna</artifactId>
      <version>5.19.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <!--
      Only @FormatMethod is used, on the constructors that hand a format
      string and its arguments to String.format. The annotation is not
      retained at runtime, so the scope is "provided": it must not reach
      the classpath of anything that depends on eo-runtime.
      -->
      <groupId>com.google.errorprone</groupId>
      <artifactId>error_prone_annotations</artifactId>
      <version>2.50.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jul-to-slf4j</artifactId>
      <version>2.0.19</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>2.0.19</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.6.5</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.eolang</groupId>
      <artifactId>xax</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.yegor256</groupId>
      <artifactId>jaxec</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.yegor256</groupId>
      <artifactId>jhome</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.jcabi</groupId>
      <artifactId>jcabi-log</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.jcabi</groupId>
      <artifactId>jcabi-xml</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.jcabi</groupId>
      <artifactId>jcabi-manifests</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.cactoos</groupId>
      <artifactId>cactoos</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.llorllale</groupId>
      <artifactId>cactoos-matchers</artifactId>
      <version>0.25</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-params</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <!--
      Deadline, Maxmem, and Budget guard every test the transpiler makes out
      of an .eo file, so they live among the classes of the runtime and need
      JUnit to compile (#9074). The scope is "provided": a test that uses them
      brings JUnit along, while a program that only runs EO objects must not
      get JUnit on its classpath through eo-runtime.
      -->
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <!-- version from parent POM -->
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.junit-pioneer</groupId>
      <artifactId>junit-pioneer</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <!-- Deadline and Watched throw its TestAbortedException, see junit-jupiter-api above. -->
      <groupId>org.opentest4j</groupId>
      <artifactId>opentest4j</artifactId>
      <!-- version from parent POM -->
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>com.yegor256</groupId>
      <artifactId>jping</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>net.sf.saxon</groupId>
      <artifactId>Saxon-HE</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.yegor256</groupId>
      <artifactId>farea</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.yegor256</groupId>
      <artifactId>mktmp</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.yegor256</groupId>
      <artifactId>together</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.yegor256</groupId>
      <artifactId>maybeslow</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.eolang</groupId>
      <artifactId>jucs</artifactId>
      <!-- version from parent POM -->
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.github.artsok</groupId>
      <artifactId>rerunner-jupiter</artifactId>
      <version>2.1.6</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>codes.ivanov</groupId>
      <artifactId>ephpo</artifactId>
      <version>1.0.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <skipTests>${skipUTs}</skipTests>
          <runOrder>random</runOrder>
          <argLine>
            @{argLine} -Xmx${heap-size} -Xss${stack-size} -Duser.language=ru -Duser.region=RU
          </argLine>
          <systemPropertyVariables>
            <eo.version>${project.version}</eo.version>
            <junit.jupiter.execution.timeout.test.method.default>
              ${eo.deadline}s
            </junit.jupiter.execution.timeout.test.method.default>
            <eo.maxmem>${eo.maxmem}</eo.maxmem>
            <eo.coverageFile>${project.build.directory}/coverage.txt</eo.coverageFile>
            <java.util.logging.config.file>
              ${project.basedir}/src/test/resources/jul.properties
            </java.util.logging.config.file>
          </systemPropertyVariables>
          <!--
          Default surefire plugin corrupts native stdout. It means the text that was
          printed in native method will not be printed in 'mvn clean install'. This configuration
          switches surefire communication channel from default to TCP/IP and solves the bug.
          More detailed: https://stackoverflow.com/questions/55272870/surefire-maven-plugin-corrupted-stdout-by-directly-writing-to-native-stream-in
          and https://maven.apache.org/surefire/maven-surefire-plugin/examples/process-communication.html
          -->
          <forkNode implementation="org.apache.maven.plugin.surefire.extensions.SurefireForkNodeFactory"/>
          <properties>
            <configurationParameters>
              junit.jupiter.execution.parallel.enabled = true
              junit.jupiter.execution.parallel.mode.default = concurrent
              junit.jupiter.execution.parallel.mode.classes.default = concurrent
              junit.jupiter.execution.parallel.config.strategy = dynamic
              junit.jupiter.execution.parallel.config.dynamic.factor = 1
            </configurationParameters>
          </properties>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.eolang</groupId>
        <artifactId>eo-maven-plugin</artifactId>
        <version>${project.version}</version>
        <configuration>
          <foreign>${project.build.directory}/eo-foreign.csv</foreign>
          <foreignFormat>csv</foreignFormat>
          <!-- Every lint warning is an error here; nothing may be tolerated. -->
          <failOnWarning>true</failOnWarning>
          <skipExperimentalLints>true</skipExperimentalLints>
          <offline>true</offline>
          <ignoreRuntime>true</ignoreRuntime>
          <!--
          Cache is disabled because it is keyed on the plugin version
          (1.0-SNAPSHOT during development), so any plugin or configuration
          change would be silently ignored until the cache is cleared manually.
          -->
          <cacheEnabled>false</cacheEnabled>
          <!-- Tests assert on precise .eo locations in panics (off by default). -->
          <trackLocations>true</trackLocations>
          <!-- The seconds one run of phino may take on one entry of 'eo:lower'. -->
          <loweringBudget>60</loweringBudget>
          <!-- The largest number of nested steps one run of phino may take in 'eo:lower'. -->
          <maxMorphingSteps>100</maxMorphingSteps>
        </configuration>
        <executions>
          <execution>
            <id>compile</id>
            <goals>
              <goal>register</goal>
              <goal>format</goal>
              <goal>compile</goal>
              <goal>inference</goal>
              <goal>dealpha</goal>
              <goal>inference-report</goal>
              <goal>lower</goal>
              <goal>transpile</goal>
              <goal>atoms-table</goal>
              <goal>unplace</goal>
              <goal>unspile</goal>
            </goals>
            <configuration>
              <skipSourceLints>
                <!-- https://github.com/objectionary/lints/issues/1279 -->
                <lint>mandatory-package</lint>
                <!-- https://github.com/objectionary/lints/issues/1273 -->
                <lint>package-member-without-void</lint>
                <!--
                'redundant-object' sees one file at a time and counts only the
                references written relative to the current object, so every
                public attribute of a library object, from 'win32.rdonly' to
                'tuple.empty', looks unused to it (objectionary/lints#1276).
                -->
                <lint>redundant-object</lint>
                <!--
                @todo #6985:30min Stop skipping 'many-void-attributes' here.
                The rule caps a formation at five voids to keep it callable,
                but it counts 'ρ' among them, and 'string.regex.pattern.yes'
                has five real ones. Writing the receiver down did not add an
                argument, so the cap now bites any head honest enough to
                declare what it already had. Remove this entry once
                objectionary/lints#1299 leaves the receiver out of the count.
                -->
                <lint>many-void-attributes</lint>
                <!--
                @todo #8654:30min Stop skipping 'unit-test-is-not-verb' here.
                Lints 0.4.9 registers a lint that 0.4.8 shipped but never ran,
                and it wants a test name to open with a verb in singular form,
                which no 'can-...' name in this module does.
                -->
                <lint>unit-test-is-not-verb</lint>
                <!--
                @todo #8654:30min Stop skipping 'invalid-name-notation' here.
                The lint holds a name to '[a-z]+(-[a-z]+)*', which leaves no
                room for the digit in 'bytes/as-u8.eo:12' or in its siblings
                from 'as-i8' to 'as-u64'.
                -->
                <lint>invalid-name-notation</lint>
                <!--
                'broad-scope' asks for a private attribute read by one sibling
                to move inside it, which for a recursive head means computing
                it again on every step: 'i64.div' hoists 'bit' and 'dividend'
                out of 'looped' on purpose. Thirty-four of its forty-six
                reports sit in 'string/regex.eo', whose objects share one
                vocabulary across the whole parser, and #8654 holds the rest.
                -->
                <lint>broad-scope</lint>
              </skipSourceLints>
              <!--
              Objects with an optional fallback argument, like 'string.as-fixed'
              or 'win32', are applied with and without it on purpose, and the
              lint reads every such pair as an inconsistency.
              -->
              <skipProgramLints>
                <lint>inconsistent-args</lint>
              </skipProgramLints>
              <!--
              A package is named here once its members reach their receiver
              through '^' instead of through a first void, since the two only
              work together: with the void still there the merged member never
              gets a receiver, and with '^' but no merge it has no rho to read.
              -->
              <keepBinaries>
                <glob>org/eolang/package-info.class</glob>
              </keepBinaries>
            </configuration>
          </execution>
          <execution>
            <id>coverage-report</id>
            <phase>verify</phase>
            <goals>
              <goal>coverage-report</goal>
            </goals>
            <configuration>
              <minCoverage>55</minCoverage>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-javadoc-plugin</artifactId>
        <configuration>
          <!--
          Transpiled atoms carry their XMIR in the docblock, where Javadoc
          reads the <o> elements as unknown HTML; only the handwritten
          sources are documented
          -->
          <sourcepath>${project.basedir}/src/main/java</sourcepath>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <executions>
          <execution>
            <id>snippet-test</id>
            <phase>integration-test</phase>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
            <configuration>
              <argLine>
                @{argLine} -Xmx${heap-size} -Xss${stack-size} -Duser.language=ru -Duser.region=RU
              </argLine>
              <systemPropertyVariables combine.children="append">
                <java.class.path>${project.build.outputDirectory}</java.class.path>
                <xmir.xsd>${project.basedir}/../eo-parser/src/main/resources/XMIR.xsd</xmir.xsd>
              </systemPropertyVariables>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  <profiles>
    <profile>
      <id>jacoco</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <executions>
              <execution>
                <id>jacoco-initialize</id>
                <goals>
                  <goal>prepare-agent</goal>
                </goals>
              </execution>
              <execution>
                <id>jacoco-check</id>
                <phase>test</phase>
                <goals>
                  <goal>check</goal>
                  <goal>report</goal>
                </goals>
                <configuration>
                  <rules>
                    <rule>
                      <element>BUNDLE</element>
                      <limits>
                        <limit>
                          <counter>INSTRUCTION</counter>
                          <value>COVEREDRATIO</value>
                          <minimum>0.14</minimum>
                        </limit>
                        <limit>
                          <counter>LINE</counter>
                          <value>COVEREDRATIO</value>
                          <minimum>0.13</minimum>
                        </limit>
                        <limit>
                          <counter>BRANCH</counter>
                          <value>COVEREDRATIO</value>
                          <minimum>0.03</minimum>
                        </limit>
                        <limit>
                          <counter>COMPLEXITY</counter>
                          <value>COVEREDRATIO</value>
                          <minimum>0.08</minimum>
                        </limit>
                        <limit>
                          <counter>METHOD</counter>
                          <value>COVEREDRATIO</value>
                          <minimum>0.12</minimum>
                        </limit>
                        <limit>
                          <counter>CLASS</counter>
                          <value>MISSEDCOUNT</value>
                          <maximum>1514</maximum>
                        </limit>
                      </limits>
                    </rule>
                  </rules>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>
    <profile>
      <id>qulice</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.eolang</groupId>
            <artifactId>eo-maven-plugin</artifactId>
            <configuration>
              <skipLinting>false</skipLinting>
            </configuration>
          </plugin>
          <plugin>
            <groupId>com.qulice</groupId>
            <artifactId>qulice-maven-plugin</artifactId>
            <executions>
              <execution>
                <!--
                The check runs before "prepare-package", where "unspile"
                deletes the transpiled .class files from target/classes.
                Qulice forks javac over the test sources, and those sources
                mention generated objects like EOnumber and EOnop, which
                javac can only resolve while their classes are still there.
                -->
                <id>jcabi-qulice-check</id>
                <phase>process-test-classes</phase>
              </execution>
            </executions>
            <configuration>
              <errorprone>
                <!--
                PhDefault.equals() compares hash codes on purpose. Every
                decorator of Phi (PhOnce, PhSafe, PhCoverage, Data.ToPhi)
                delegates both equals() and hashCode() to its origin, so a
                wrapper has to compare equal to what it wraps. Comparing
                identities instead breaks that, and even breaks reflexivity:
                x.equals(x) turns into origin == x for every wrapper.
                -->
                <errorprone>-Xep:EqualsUsingHashCode:OFF</errorprone>
              </errorprone>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.codehaus.gmaven</groupId>
            <artifactId>groovy-maven-plugin</artifactId>
            <executions>
              <execution>
                <id>project-validate</id>
                <phase>verify</phase>
                <goals>
                  <goal>execute</goal>
                </goals>
                <configuration>
                  <source>${project.basedir}/src/test/groovy/verify.groovy</source>
                </configuration>
              </execution>
            </executions>
            <dependencies>
              <dependency>
                <groupId>org.apache.groovy</groupId>
                <artifactId>groovy-xml</artifactId>
                <version>6.0.0</version>
              </dependency>
            </dependencies>
          </plugin>
        </plugins>
      </build>
    </profile>
    <profile>
      <id>hone</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.eolang</groupId>
            <artifactId>hone-maven-plugin</artifactId>
            <version>0.29.4</version>
            <executions>
              <execution>
                <goals>
                  <goal>pull</goal>
                  <goal>optimize</goal>
                  <goal>rmi</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
</project>
