1
0
Fork 0

Throw exception on invalid file URI

pull/35/head
Felix Becker 2016-10-10 12:13:42 +02:00
parent a43d2b2a0f
commit 6611a30d90
4 changed files with 42 additions and 10 deletions

View File

@ -3,6 +3,8 @@ declare(strict_types = 1);
namespace LanguageServer; namespace LanguageServer;
use InvalidArgumentException;
/** /**
* Recursively Searches files with matching filename, starting at $path. * Recursively Searches files with matching filename, starting at $path.
* *
@ -29,18 +31,30 @@ function findFilesRecursive(string $path, string $pattern): array {
*/ */
function pathToUri(string $filepath): string { function pathToUri(string $filepath): string {
$filepath = trim(str_replace('\\', '/', $filepath), '/'); $filepath = trim(str_replace('\\', '/', $filepath), '/');
$filepath = implode('/', array_map('urlencode', explode('/', $filepath))); $parts = explode('/', $filepath);
// Don't %-encode the colon after a Windows drive letter
$first = array_shift($parts);
if (substr($first, -1) !== ':') {
$first = urlencode($first);
}
$parts = array_map('urlencode', $parts);
array_unshift($parts, $first);
$filepath = implode('/', $parts);
return 'file:///' . $filepath; return 'file:///' . $filepath;
} }
/** /**
* Transforms URI into file path * Transforms URI into file path
* *
* @param string $uri * @param string $uri
* @return string * @return string
*/ */
function uriToPath(string $uri) function uriToPath(string $uri)
{ {
$filepath = urldecode(parse_url($uri)['path']); $fragments = parse_url($uri);
if ($fragments === null || !isset($fragments['scheme']) || $fragments['scheme'] !== 'file') {
throw new InvalidArgumentException("Not a valid file URI: $uri");
}
$filepath = urldecode($fragments['path']);
return strpos($filepath, ':') === false ? $filepath : str_replace('/', '\\', $filepath); return strpos($filepath, ':') === false ? $filepath : str_replace('/', '\\', $filepath);
} }

View File

@ -16,7 +16,7 @@ class FormatterTest extends TestCase
$input = file_get_contents(__DIR__ . '/../fixtures/format.php'); $input = file_get_contents(__DIR__ . '/../fixtures/format.php');
$output = file_get_contents(__DIR__ . '/../fixtures/format_expected.php'); $output = file_get_contents(__DIR__ . '/../fixtures/format_expected.php');
$edits = $formatter->format($input, 'whatever'); $edits = $formatter->format($input, 'file:///whatever');
$this->assertSame($output, $edits[0]->newText); $this->assertSame($output, $edits[0]->newText);
} }
@ -25,7 +25,7 @@ class FormatterTest extends TestCase
$formatter = new Formatter(); $formatter = new Formatter();
$expected = file_get_contents(__DIR__ . '/../fixtures/format_expected.php'); $expected = file_get_contents(__DIR__ . '/../fixtures/format_expected.php');
$edits = $formatter->format($expected, 'whatever'); $edits = $formatter->format($expected, 'file:///whatever');
$this->assertSame([], $edits); $this->assertSame([], $edits);
} }
} }

View File

@ -7,6 +7,7 @@ use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{Server, Client, LanguageClient, Project}; use LanguageServer\{Server, Client, LanguageClient, Project};
use LanguageServer\Protocol\{TextDocumentIdentifier, TextDocumentItem, FormattingOptions}; use LanguageServer\Protocol\{TextDocumentIdentifier, TextDocumentItem, FormattingOptions};
use function LanguageServer\{pathToUri, uriToPath};
class FormattingTest extends TestCase class FormattingTest extends TestCase
{ {
@ -27,19 +28,21 @@ class FormattingTest extends TestCase
$client = new LanguageClient(new MockProtocolStream()); $client = new LanguageClient(new MockProtocolStream());
$project = new Project($client); $project = new Project($client);
$textDocument = new Server\TextDocument($project, $client); $textDocument = new Server\TextDocument($project, $client);
$path = realpath(__DIR__ . '/../../../fixtures/format.php');
$uri = pathToUri($path);
// Trigger parsing of source // Trigger parsing of source
$textDocumentItem = new TextDocumentItem(); $textDocumentItem = new TextDocumentItem();
$textDocumentItem->uri = 'whatever'; $textDocumentItem->uri = $uri;
$textDocumentItem->languageId = 'php'; $textDocumentItem->languageId = 'php';
$textDocumentItem->version = 1; $textDocumentItem->version = 1;
$textDocumentItem->text = file_get_contents(__DIR__ . '/../../../fixtures/format.php'); $textDocumentItem->text = file_get_contents($path);
$textDocument->didOpen($textDocumentItem); $textDocument->didOpen($textDocumentItem);
// how code should look after formatting // how code should look after formatting
$expected = file_get_contents(__DIR__ . '/../../../fixtures/format_expected.php'); $expected = file_get_contents(__DIR__ . '/../../../fixtures/format_expected.php');
// Request formatting // Request formatting
$result = $textDocument->formatting(new TextDocumentIdentifier('whatever'), new FormattingOptions()); $result = $textDocument->formatting(new TextDocumentIdentifier($uri), new FormattingOptions());
$this->assertEquals([0 => [ $this->assertEquals([0 => [
'range' => [ 'range' => [
'start' => [ 'start' => [

View File

@ -4,6 +4,7 @@ declare(strict_types = 1);
namespace LanguageServer\Tests\Utils; namespace LanguageServer\Tests\Utils;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
use function LanguageServer\{pathToUri, uriToPath}; use function LanguageServer\{pathToUri, uriToPath};
class FileUriTest extends TestCase class FileUriTest extends TestCase
@ -24,11 +25,11 @@ class FileUriTest extends TestCase
// special chars are escaped // special chars are escaped
$uri = pathToUri('c:/path/to/file/dürüm döner.php'); $uri = pathToUri('c:/path/to/file/dürüm döner.php');
$this->assertEquals('file:///c%3A/path/to/file/d%C3%BCr%C3%BCm+d%C3%B6ner.php', $uri); $this->assertEquals('file:///c:/path/to/file/d%C3%BCr%C3%BCm+d%C3%B6ner.php', $uri);
//backslashes are transformed //backslashes are transformed
$uri = pathToUri('c:\\foo\\bar.baz'); $uri = pathToUri('c:\\foo\\bar.baz');
$this->assertEquals('file:///c%3A/foo/bar.baz', $uri); $this->assertEquals('file:///c:/foo/bar.baz', $uri);
} }
public function testUriToPath() public function testUriToPath()
@ -51,4 +52,18 @@ class FileUriTest extends TestCase
$uri = 'file:///c:/foo/bar.baz'; $uri = 'file:///c:/foo/bar.baz';
$this->assertEquals('c:\\foo\\bar.baz', uriToPath($uri)); $this->assertEquals('c:\\foo\\bar.baz', uriToPath($uri));
} }
public function testUriToPathForUnknownProtocol()
{
$this->expectException(InvalidArgumentException::class);
$uri = 'vfs:///whatever';
uriToPath($uri);
}
public function testUriToPathForInvalidProtocol()
{
$this->expectException(InvalidArgumentException::class);
$uri = 'http://www.google.com';
uriToPath($uri);
}
} }