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
27 changes: 23 additions & 4 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---

name: 🧪 Unit testing
name: 🧪

on: # yamllint disable-line rule:truthy
pull_request:
Expand All @@ -16,7 +16,7 @@ jobs:
runs-on: ${{ matrix.os }}
concurrency:
cancel-in-progress: true
group: code-coverage-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}-${{ matrix.php-version }}-${{ matrix.dependencies }}
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}-${{ matrix.php-version }}-${{ matrix.dependencies }}
strategy:
fail-fast: true
matrix:
Expand All @@ -37,6 +37,11 @@ jobs:
ini-values: error_reporting=E_ALL
coverage: xdebug

- name: Configure environment
run: |
export COMPOSER_ROOT_VERSION=$(/usr/bin/jq --null-input --raw-output 'first(inputs["."])' resources/version.json)
echo COMPOSER_ROOT_VERSION=$COMPOSER_ROOT_VERSION >> $GITHUB_ENV

- name: 🛠️ Setup problem matchers
run: |
echo "::add-matcher::${{ runner.tool_cache }}/php.json"
Expand Down Expand Up @@ -65,21 +70,30 @@ jobs:
runs-on: ${{ matrix.os }}
concurrency:
cancel-in-progress: true
group: testing-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}-${{ matrix.php-version }}-${{ matrix.dependencies }}
group: ${{ matrix.type }}-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}-${{ matrix.php-version }}-${{ matrix.dependencies }}
strategy:
fail-fast: false
matrix:
type:
- unit
- acc
os:
- ubuntu-latest
php-version:
- '8.1'
- '8.2'
- '8.3'
- '8.4'
- '8.5'
dependencies:
- lowest
- locked
- highest
include:
- php-version: "8.5"
os: ubuntu-latest
type: "arch"
dependencies: "locked"
steps:
- name: 📦 Check out the codebase
uses: actions/checkout@v5
Expand All @@ -90,6 +104,11 @@ jobs:
php-version: ${{ matrix.php-version }}
ini-values: error_reporting=E_ALL

- name: Configure environment
run: |
export COMPOSER_ROOT_VERSION=$(/usr/bin/jq --null-input --raw-output 'first(inputs["."])' resources/version.json)
echo COMPOSER_ROOT_VERSION=$COMPOSER_ROOT_VERSION >> $GITHUB_ENV

- name: 🛠️ Setup problem matchers
run: |
echo "::add-matcher::${{ runner.tool_cache }}/php.json"
Expand All @@ -104,4 +123,4 @@ jobs:
dependency-versions: ${{ matrix.dependencies }}

- name: 🧪 Run tests
run: composer test
run: composer test:${{ matrix.type }}
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"phpunit/phpunit": "^10.5",
"spiral/code-style": "^2.3.0",
"ta-tikoma/phpunit-architecture-test": "^0.8.5",
"vimeo/psalm": "^6.13"
"vimeo/psalm": "^6.13",
"internal/dload": "^1.11"
},
"minimum-stability": "dev",
"prefer-stable": true,
Expand All @@ -41,6 +42,9 @@
}
},
"scripts": {
"post-update-cmd": [
"dload get --no-interaction"
],
"cs:diff": "php-cs-fixer fix --dry-run -v --diff",
"cs:fix": "php-cs-fixer fix -v",
"infect": [
Expand Down
14 changes: 14 additions & 0 deletions dload.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<dload xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/internal/dload/dload.xsd"
>
<actions>
<download software="toml-test" version="^2.1" extract-path="runtime"/>
</actions>
<registry>
<software name="TOML Test" alias="toml-test">
<repository uri="toml-lang/toml-test" asset-pattern="/^toml-test-.*/" type="github" />
<binary name="toml-test" pattern="/^toml-test-.*/" version-command="version"/>
</software>
</registry>
</dload>
5 changes: 4 additions & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
bootstrap="vendor/autoload.php"
colors="true"
cacheResultFile="runtime/phpunit/result.cache"
failOnWarning="true"
failOnWarning="false"
failOnRisky="true"
stderr="true"
beStrictAboutOutputDuringTests="true"
Expand All @@ -17,6 +17,9 @@
<testsuite name="Arch">
<directory>tests/Arch</directory>
</testsuite>
<testsuite name="Acceptance">
<directory>tests/Acceptance</directory>
</testsuite>
</testsuites>
<coverage>
<report>
Expand Down
1 change: 0 additions & 1 deletion src/Encoder/ArrayToDocumentConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ public function convert(array $data): Document
* ['github.token' => ['key' => 'val']]
*
* @param array<string, mixed> $data
* @param string $prefix
* @return array<string, mixed>
*/
private function flattenData(array $data, string $prefix = ''): array
Expand Down
1 change: 1 addition & 0 deletions src/Encoder/ValueFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ final class ValueFactory
public static function create(mixed $value): Value
{
return match (true) {
$value instanceof Value => $value,
\is_string($value) => self::createString($value),
\is_int($value) => self::createInteger($value),
\is_float($value) => self::createFloat($value),
Expand Down
8 changes: 7 additions & 1 deletion src/Node/Document.php
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,13 @@ private function addTable(array &$result, Table $table): void

foreach ($table->name->segments as $segment) {
$current[$segment] ??= [];
$current = &$current[$segment];

// If the segment is an array-of-tables, navigate into the last element
if (\is_array($current[$segment]) and \array_is_list($current[$segment]) and $current[$segment] !== []) {
$current = &$current[$segment][\count($current[$segment]) - 1];
} else {
$current = &$current[$segment];
}
}

foreach ($table->entries as $entry) {
Expand Down
20 changes: 11 additions & 9 deletions src/Node/Key.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ public function __construct(
parent::__construct($position);
}

/**
* Quotes a key segment if it contains special characters.
*/
public static function quoteIfNeeded(string $segment): string
{
return self::needsQuoting($segment)
? '"' . \addcslashes($segment, "\"\\\n\r\t") . '"'
: $segment;
}

public function isSimple(): bool
{
return \count($this->segments) === 1;
Expand Down Expand Up @@ -46,15 +56,7 @@ public function getLastSegment(): string

public function __toString(): string
{
$result = [];

foreach ($this->segments as $segment) {
$result[] = self::needsQuoting($segment)
? '"' . \addcslashes($segment, "\"\\\n\r\t") . '"'
: $segment;
}

return \implode('.', $result);
return \implode('.', \array_map(self::quoteIfNeeded(...), $this->segments));
}

/**
Expand Down
21 changes: 20 additions & 1 deletion src/Node/Value/DateTimeValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
*/
final class DateTimeValue extends Value
{
public readonly string $raw;

public function __construct(
public readonly \DateTimeImmutable $value,
public readonly DateTimeType $type,
public readonly string $raw,
string $raw,
Position $position,
) {
parent::__construct($position);
$this->raw = self::normalize($raw);
}

public function toPhpValue(): \DateTimeImmutable
Expand All @@ -29,4 +32,20 @@ public function __toString(): string
{
return $this->raw;
}

/**
* Normalizes the raw datetime string:
* - Replaces space/t separator with T
* - Injects :00 seconds when omitted
*/
private static function normalize(string $raw): string
{
// Replace space or lowercase 't' separator with 'T'
$raw = \preg_replace('/^(\d{4}-\d{2}-\d{2})[ t]/', '$1T', $raw);

// Inject :00 seconds when omitted (HH:MM followed by offset or end)
$raw = \preg_replace('/(T)(\d{2}:\d{2})([Z+\-]|$)/', '$1$2:00$3', $raw);

return $raw;
}
}
3 changes: 2 additions & 1 deletion src/Node/Value/InlineTableValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Internal\Toml\Node\Value;

use Internal\Toml\Node\Entry;
use Internal\Toml\Node\Key;
use Internal\Toml\Node\MultiLineNode;
use Internal\Toml\Node\Position;

Expand Down Expand Up @@ -60,7 +61,7 @@ public function __toString(): string

$parts = [];
foreach ($this->pairs as $key => $value) {
$parts[] = $key . ' = ' . (string) $value;
$parts[] = Key::quoteIfNeeded($key) . ' = ' . (string) $value;
}

return '{' . \implode(', ', $parts) . '}';
Expand Down
6 changes: 5 additions & 1 deletion src/Node/Value/LocalTimeValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@
*/
final class LocalTimeValue extends Value
{
public readonly string $value;

public function __construct(
public readonly string $value, // "07:32:00.999999"
string $value, // "07:32:00.999999"
Position $position,
) {
parent::__construct($position);
// Normalize: inject :00 seconds when omitted (HH:MM → HH:MM:00)
$this->value = \preg_match('/^\d{2}:\d{2}$/', $value) ? $value . ':00' : $value;
}

public function toPhpValue(): string
Expand Down
Loading
Loading