1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Introduce --map-folder switch

And create PathMapper based on its value
This commit is contained in:
Bruce Weirdan 2023-07-23 02:10:49 +02:00
parent 8a51aaedd4
commit 6eb7a688d1
3 changed files with 73 additions and 10 deletions

View File

@ -10,6 +10,7 @@ use Psalm\Internal\Fork\PsalmRestarter;
use Psalm\Internal\IncludeCollector;
use Psalm\Internal\LanguageServer\ClientConfiguration;
use Psalm\Internal\LanguageServer\LanguageServer as LanguageServerLanguageServer;
use Psalm\Internal\LanguageServer\PathMapper;
use Psalm\Report;
use function array_key_exists;
@ -75,6 +76,7 @@ final class LanguageServer
'find-dead-code',
'help',
'root:',
'map-folder::',
'use-ini-defaults',
'version',
'tcp:',
@ -127,6 +129,14 @@ final class LanguageServer
// get options from command line
$options = getopt(implode('', $valid_short_options), $valid_long_options);
if ($options === false) {
// shouldn't really happen, but just in case
fwrite(
STDERR,
'Failed to get CLI args' . PHP_EOL,
);
exit(1);
}
if (!array_key_exists('use-ini-defaults', $options)) {
ini_set('display_errors', '1');
@ -169,6 +179,14 @@ final class LanguageServer
-r, --root
If running Psalm globally you'll need to specify a project root. Defaults to cwd
--map-folder[=SERVER_FOLDER:CLIENT_FOLDER]
Specify folder to map between the client and the server. Use this when the client
and server have different views of the filesystem (e.g. in a docker container).
Defaults to mapping the rootUri provided by the client to the server's cwd,
or `-r` if provided.
No mapping is done when this option is not specified.
--find-dead-code
Look for dead code
@ -254,8 +272,6 @@ final class LanguageServer
$current_dir = $root_path . DIRECTORY_SEPARATOR;
}
$server_start_dir = $current_dir;
$vendor_dir = CliUtils::getVendorDir($current_dir);
$include_collector = new IncludeCollector();
@ -293,6 +309,8 @@ final class LanguageServer
setlocale(LC_CTYPE, 'C');
$path_mapper = self::createPathMapper($options, $current_dir);
$path_to_config = CliUtils::getPathToConfig($options);
if (isset($options['tcp'])) {
@ -396,6 +414,49 @@ final class LanguageServer
$clientConfiguration->TCPServerAddress = $options['tcp'] ?? null;
$clientConfiguration->TCPServerMode = isset($options['tcp-server']);
LanguageServerLanguageServer::run($config, $clientConfiguration, $current_dir, $server_start_dir, $inMemory);
LanguageServerLanguageServer::run($config, $clientConfiguration, $current_dir, $path_mapper, $inMemory);
}
/** @param array<string,string|false|list<string|false>> $options */
private static function createPathMapper(array $options, string $server_start_dir): PathMapper
{
if (!isset($options['map-folder'])) {
// dummy no-op mapper
return new PathMapper('/', '/');
}
$map_folder = $options['map-folder'];
if ($map_folder === false) {
// autoconfigured mapper
return new PathMapper($server_start_dir, null);
}
if (is_string($map_folder)) {
if (strpos($map_folder, ':') === false) {
fwrite(
STDERR,
'invalid format for --map-folder option' . PHP_EOL,
);
exit(1);
}
/** @psalm-suppress PossiblyUndefinedArrayOffset we just checked that we have the separator*/
[$server_dir, $client_dir] = explode(':', $map_folder, 2);
if (!strlen($server_dir) || !strlen($client_dir)) {
fwrite(
STDERR,
'invalid format for --map-folder option, '
. 'neither SERVER_FOLDER nor CLIENT_FOLDER can be empty' . PHP_EOL,
);
exit(1);
}
return new PathMapper($server_dir, $client_dir);
}
fwrite(
STDERR,
'--map-folder option can only be specified once' . PHP_EOL,
);
exit(1);
}
}

View File

@ -153,7 +153,7 @@ class LanguageServer extends Dispatcher
Codebase $codebase,
ClientConfiguration $clientConfiguration,
Progress $progress,
string $server_start_dir
PathMapper $path_mapper
) {
parent::__construct($this, '/');
@ -163,6 +163,8 @@ class LanguageServer extends Dispatcher
$this->codebase = $codebase;
$this->path_mapper = $path_mapper;
$this->protocolWriter = $writer;
$this->protocolReader = $reader;
@ -245,7 +247,6 @@ class LanguageServer extends Dispatcher
$this->client = new LanguageClient($reader, $writer, $this, $clientConfiguration);
$this->path_mapper = new PathMapper($server_start_dir, null);
$this->logInfo("Psalm Language Server ".PSALM_VERSION." has started.");
}
@ -257,7 +258,7 @@ class LanguageServer extends Dispatcher
Config $config,
ClientConfiguration $clientConfiguration,
string $base_dir,
string $server_start_dir,
PathMapper $path_mapper,
bool $inMemory = false
): void {
$progress = new Progress();
@ -330,7 +331,7 @@ class LanguageServer extends Dispatcher
$codebase,
$clientConfiguration,
$progress,
$server_start_dir,
$path_mapper,
);
Loop::run();
} elseif ($clientConfiguration->TCPServerMode && $clientConfiguration->TCPServerAddress) {
@ -354,7 +355,7 @@ class LanguageServer extends Dispatcher
$codebase,
$clientConfiguration,
$progress,
$server_start_dir,
$path_mapper,
);
Loop::run();
}
@ -368,7 +369,7 @@ class LanguageServer extends Dispatcher
$codebase,
$clientConfiguration,
$progress,
$server_start_dir,
$path_mapper,
);
Loop::run();
}

View File

@ -9,6 +9,7 @@ use Psalm\Internal\Analyzer\ProjectAnalyzer;
use Psalm\Internal\LanguageServer\ClientConfiguration;
use Psalm\Internal\LanguageServer\LanguageServer;
use Psalm\Internal\LanguageServer\Message;
use Psalm\Internal\LanguageServer\PathMapper;
use Psalm\Internal\LanguageServer\Progress;
use Psalm\Internal\Provider\FakeFileProvider;
use Psalm\Internal\Provider\Providers;
@ -85,7 +86,7 @@ class DiagnosticTest extends AsyncTestCase
$this->codebase,
$clientConfiguration,
new Progress,
getcwd(),
new PathMapper(getcwd(), getcwd()),
);
$write->on('message', function (Message $message) use ($deferred, $server): void {