1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Add path mapper

This commit is contained in:
Bruce Weirdan 2023-07-23 00:04:25 +02:00
parent f634a0047a
commit a68c4804f4
2 changed files with 132 additions and 0 deletions

View File

@ -0,0 +1,57 @@
<?php
namespace Psalm\Internal\LanguageServer;
/** @internal */
final class PathMapper
{
private string $serverRoot;
private ?string $clientRoot;
public function __construct(string $serverRoot, ?string $clientRoot = null)
{
$this->serverRoot = $this->sanitizeFolderPath($serverRoot);
$this->clientRoot = $this->sanitizeFolderPath($clientRoot);
}
public function configureClientRoot(string $clientRoot): void
{
// ignore if preconfigured
if ($this->clientRoot === null) {
$this->clientRoot = $this->sanitizeFolderPath($clientRoot);
}
}
public function mapClientToServer(string $clientPath): string
{
if ($this->clientRoot === null) {
return $clientPath;
}
if (substr($clientPath, 0, strlen($this->clientRoot)) === $this->clientRoot) {
return $this->serverRoot . substr($clientPath, strlen($this->clientRoot));
}
return $clientPath;
}
public function mapServerToClient(string $serverPath): string
{
if ($this->clientRoot === null) {
return $serverPath;
}
if (substr($serverPath, 0, strlen($this->serverRoot)) === $this->serverRoot) {
return $this->clientRoot . substr($serverPath, strlen($this->serverRoot));
}
return $serverPath;
}
/** @return ($path is null ? null : string) */
private function sanitizeFolderPath(?string $path): ?string
{
if ($path === null) {
return $path;
}
return rtrim($path, '/');
}
}

View File

@ -0,0 +1,75 @@
<?php
namespace Psalm\Tests\LanguageServer;
use PHPUnit\Framework\TestCase;
use Psalm\Internal\LanguageServer\PathMapper;
final class PathMapperTest extends TestCase
{
public function testUsesUpdatedClientRoot(): void
{
$mapper = new PathMapper('/var/www');
$mapper->configureClientRoot('/home/user/src/project');
$this->assertSame(
'/home/user/src/project/filename.php',
$mapper->mapServerToClient('/var/www/filename.php')
);
}
public function testIgnoresClientRootIfItWasPreconfigures(): void
{
$mapper = new PathMapper('/var/www', '/home/user/src/project');
// this will be ignored
$mapper->configureClientRoot('/home/anotheruser/Projects/project');
$this->assertSame(
'/home/user/src/project/filename.php',
$mapper->mapServerToClient('/var/www/filename.php')
);
}
/**
* @dataProvider mappingProvider
*/
public function testMapsClientToServer(
string $serverRoot,
?string $clientRootPreconfigured,
string $clientRootProvidedLater,
string $clientPath,
string $serverPath
): void {
$mapper = new PathMapper($serverRoot, $clientRootPreconfigured);
$mapper->configureClientRoot($clientRootProvidedLater);
$this->assertSame(
$serverPath,
$mapper->mapClientToServer($clientPath)
);
}
/** @dataProvider mappingProvider */
public function testMapsServerToClient(
string $serverRoot,
?string $clientRootPreconfigured,
string $clientRootProvidedLater,
string $clientPath,
string $serverPath
): void {
$mapper = new PathMapper($serverRoot, $clientRootPreconfigured);
$mapper->configureClientRoot($clientRootProvidedLater);
$this->assertSame(
$clientPath,
$mapper->mapServerToClient($serverPath)
);
}
/** @return iterable<int, array{string, string|null, string, string, string}> */
public static function mappingProvider(): iterable
{
yield ["/var/a", null, "/user/project", "/user/project/filename.php", "/var/a/filename.php"];
yield ["/var/a", "/user/project", "/whatever", "/user/project/filename.php", "/var/a/filename.php"];
yield ["/var/a/", "/user/project", "/whatever", "/user/project/filename.php", "/var/a/filename.php"];
yield ["/var/a", "/user/project/", "/whatever", "/user/project/filename.php", "/var/a/filename.php"];
yield ["/var/a/", "/user/project/", "/whatever", "/user/project/filename.php", "/var/a/filename.php"];
}
}