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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ All notable changes are documented here. The format is based on [Keep a Changelo
- `phalcon/talon` moved from `^0.8` to `^0.9`.
- `stub:publish` with no name leaves out the `project-*` stubs that `new` renders. They have an effect only in the directory that `new` puts the project into; publish one by name. A `project-*` name goes where `new` reads it - the working directory, or `--directory` - with the `adr` flavor, and needs no `crest.php`. [#8](https://github.com/phalcon/crest/issues/8)
- Rendering a stub now fails when a placeholder has no value, and the error names the stub file. A published copy that kept a placeholder crest no longer sends put the raw `{{ name }}` into the generated file. [#8](https://github.com/phalcon/crest/issues/8)
- With no `crest.php`, the error for a `composer.json` whose psr-4 directories do not exist now names those directories: `no crest.php and no usable psr-4 autoload entry found; these psr-4 directories do not exist: 'src'`. Before, the message did not say that a missing directory was the cause. [#18](https://github.com/phalcon/crest/issues/18)

### Fixed

Expand Down
5 changes: 0 additions & 5 deletions resources/infection.json5
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,6 @@
// array_values() changes nothing at runtime. It stays because
// table() declares list<list<string>> and PHPStan holds it to that.
"ignore": ["Crest\\Command\\Route\\ListCommand::handle"]
},
"UnwrapTrim": {
// is_dir() accepts a doubled separator, so trimming the psr-4
// target changes nothing about which directory is found.
"ignore": ["Crest\\Project\\Config::infer"]
}
}
}
19 changes: 16 additions & 3 deletions src/Project/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,14 @@ private static function infer(string $directory): self
throw new Exception('no crest.php and no composer.json found');
}

$psr4 = self::psr4Map($directory);
$psr4 = self::psr4Map($directory);
$missing = [];

foreach ($psr4 as $prefix => $target) {
if (false === is_dir($directory . '/' . trim($target, '/'))) {
$target = trim($target, '/');

if (false === is_dir($directory . '/' . $target)) {
$missing[] = "'" . $target . "'";
continue;
}

Expand All @@ -210,7 +214,16 @@ private static function infer(string $directory): self
);
}

throw new Exception('no crest.php and no usable psr-4 autoload entry found');
if ([] === $missing) {
throw new Exception('no crest.php and no usable psr-4 autoload entry found');
}

throw new Exception(
sprintf(
'no crest.php and no usable psr-4 autoload entry found; these psr-4 directories do not exist: %s',
implode(', ', $missing)
)
);
}

/**
Expand Down
30 changes: 29 additions & 1 deletion tests/Unit/Project/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ public function testAdrGetsADefaultPathForEveryGeneratedArtifact(): void
);
}

public function testComposerJsonWithoutPsr4EntriesThrows(): void
{
// No psr-4 entry at all, so there is no missing directory to name.
// Anchored: the message with a directory list starts the same way.
$this->writeComposerJson([]);

$this->expectException(Exception::class);
$this->expectExceptionMessageMatches('/^no crest\.php and no usable psr-4 autoload entry found$/');

Config::discover($this->root);
}

public function testCrestPhpMayDeclareTheNamespaceExplicitly(): void
{
$this->writeComposerJson(['App\\' => 'src/']);
Expand Down Expand Up @@ -290,14 +302,30 @@ public function testNonMatchingPsr4EntriesNeverBecomeTheBestMatch(): void
$this->assertSame('App\Action', Config::discover($this->root)->namespaceFor('action'));
}

public function testNoUsablePsr4EntryNamesEveryMissingDirectory(): void
{
$this->writeComposerJson(['Ghost\\' => 'missing/', 'Other\\' => 'lib']);

$this->expectException(Exception::class);
$this->expectExceptionMessage(
"no crest.php and no usable psr-4 autoload entry found; "
. "these psr-4 directories do not exist: 'missing', 'lib'"
);

Config::discover($this->root);
}

public function testNoUsablePsr4EntryThrows(): void
{
// composer.json exists but every declared directory is missing, so
// there is nothing to infer a root namespace from.
$this->writeComposerJson(['Ghost\\' => 'missing/']);

$this->expectException(Exception::class);
$this->expectExceptionMessage('no crest.php and no usable psr-4 autoload entry found');
$this->expectExceptionMessage(
"no crest.php and no usable psr-4 autoload entry found; "
. "these psr-4 directories do not exist: 'missing'"
);

Config::discover($this->root);
}
Expand Down
Loading