diff --git a/src/CallHierarchyClientCapabilities.php b/src/CallHierarchyClientCapabilities.php new file mode 100644 index 0000000..b314bde --- /dev/null +++ b/src/CallHierarchyClientCapabilities.php @@ -0,0 +1,103 @@ +dynamicRegistration = $dynamicRegistration; + } + + /** + * @param array $array + * @return self + */ + public static function fromArray(array $array, bool $allowUnknownKeys = false) + { + $map = [ + 'dynamicRegistration' => ['names' => [], 'iterable' => false], + ]; + + foreach ($array as $key => &$value) { + if (!isset($map[$key])) { + if ($allowUnknownKeys) { + unset($array[$key]); + continue; + } + + throw new RuntimeException(sprintf( + 'Parameter "%s" on class "%s" not known, known parameters: "%s"', + $key, + self::class, + implode('", "', array_keys($map)) + )); + } + + // from here we only care about arrays that can be transformed into + // objects + if (!is_array($value)) { + continue; + } + + if (empty($map[$key]['names'])) { + continue; + } + + if ($map[$key]['iterable']) { + $value = array_map(function ($object) use ($map, $key, $allowUnknownKeys) { + if (!is_array($object)) { + return $object; + } + + return self::invokeFromNames($map[$key]['names'], $object, $allowUnknownKeys) ?: $object; + }, $value); + continue; + } + + $names = $map[$key]['names']; + $value = self::invokeFromNames($names, $value, $allowUnknownKeys) ?: $value; + } + + return Invoke::new(self::class, $array); + } + + /** + * @param array $classNames + * @param array $object + */ + private static function invokeFromNames(array $classNames, array $object, bool $allowUnknownKeys): ?object + { + $lastException = null; + foreach ($classNames as $className) { + try { + // @phpstan-ignore-next-line + return call_user_func_array($className . '::fromArray', [$object, $allowUnknownKeys]); + } catch (Exception $exception) { + $lastException = $exception; + continue; + } + } + + throw $lastException; + } + +} \ No newline at end of file diff --git a/src/CallHierarchyIncomingCallsParams.php b/src/CallHierarchyIncomingCallsParams.php new file mode 100644 index 0000000..ee193d9 --- /dev/null +++ b/src/CallHierarchyIncomingCallsParams.php @@ -0,0 +1,124 @@ +item = $item; + $this->workDoneToken = $workDoneToken; + $this->partialResultToken = $partialResultToken; + } + + /** + * @param array $array + * @return self + */ + public static function fromArray(array $array, bool $allowUnknownKeys = false) + { + $map = [ + 'item' => ['names' => [CallHierarchyItem::class], 'iterable' => false], + 'workDoneToken' => ['names' => [], 'iterable' => false], + 'partialResultToken' => ['names' => [], 'iterable' => false], + ]; + + foreach ($array as $key => &$value) { + if (!isset($map[$key])) { + if ($allowUnknownKeys) { + unset($array[$key]); + continue; + } + + throw new RuntimeException(sprintf( + 'Parameter "%s" on class "%s" not known, known parameters: "%s"', + $key, + self::class, + implode('", "', array_keys($map)) + )); + } + + // from here we only care about arrays that can be transformed into + // objects + if (!is_array($value)) { + continue; + } + + if (empty($map[$key]['names'])) { + continue; + } + + if ($map[$key]['iterable']) { + $value = array_map(function ($object) use ($map, $key, $allowUnknownKeys) { + if (!is_array($object)) { + return $object; + } + + return self::invokeFromNames($map[$key]['names'], $object, $allowUnknownKeys) ?: $object; + }, $value); + continue; + } + + $names = $map[$key]['names']; + $value = self::invokeFromNames($names, $value, $allowUnknownKeys) ?: $value; + } + + return Invoke::new(self::class, $array); + } + + /** + * @param array $classNames + * @param array $object + */ + private static function invokeFromNames(array $classNames, array $object, bool $allowUnknownKeys): ?object + { + $lastException = null; + foreach ($classNames as $className) { + try { + // @phpstan-ignore-next-line + return call_user_func_array($className . '::fromArray', [$object, $allowUnknownKeys]); + } catch (Exception $exception) { + $lastException = $exception; + continue; + } + } + + throw $lastException; + } + +} \ No newline at end of file diff --git a/src/CallHierarchyIncomingCallsRequest.php b/src/CallHierarchyIncomingCallsRequest.php new file mode 100644 index 0000000..9680799 --- /dev/null +++ b/src/CallHierarchyIncomingCallsRequest.php @@ -0,0 +1,8 @@ +workDoneProgress = $workDoneProgress; + } + + /** + * @param array $array + * @return self + */ + public static function fromArray(array $array, bool $allowUnknownKeys = false) + { + $map = [ + 'workDoneProgress' => ['names' => [], 'iterable' => false], + ]; + + foreach ($array as $key => &$value) { + if (!isset($map[$key])) { + if ($allowUnknownKeys) { + unset($array[$key]); + continue; + } + + throw new RuntimeException(sprintf( + 'Parameter "%s" on class "%s" not known, known parameters: "%s"', + $key, + self::class, + implode('", "', array_keys($map)) + )); + } + + // from here we only care about arrays that can be transformed into + // objects + if (!is_array($value)) { + continue; + } + + if (empty($map[$key]['names'])) { + continue; + } + + if ($map[$key]['iterable']) { + $value = array_map(function ($object) use ($map, $key, $allowUnknownKeys) { + if (!is_array($object)) { + return $object; + } + + return self::invokeFromNames($map[$key]['names'], $object, $allowUnknownKeys) ?: $object; + }, $value); + continue; + } + + $names = $map[$key]['names']; + $value = self::invokeFromNames($names, $value, $allowUnknownKeys) ?: $value; + } + + return Invoke::new(self::class, $array); + } + + /** + * @param array $classNames + * @param array $object + */ + private static function invokeFromNames(array $classNames, array $object, bool $allowUnknownKeys): ?object + { + $lastException = null; + foreach ($classNames as $className) { + try { + // @phpstan-ignore-next-line + return call_user_func_array($className . '::fromArray', [$object, $allowUnknownKeys]); + } catch (Exception $exception) { + $lastException = $exception; + continue; + } + } + + throw $lastException; + } + +} \ No newline at end of file diff --git a/src/CallHierarchyOutgoingCallsParams.php b/src/CallHierarchyOutgoingCallsParams.php new file mode 100644 index 0000000..b3a4f7f --- /dev/null +++ b/src/CallHierarchyOutgoingCallsParams.php @@ -0,0 +1,124 @@ +item = $item; + $this->workDoneToken = $workDoneToken; + $this->partialResultToken = $partialResultToken; + } + + /** + * @param array $array + * @return self + */ + public static function fromArray(array $array, bool $allowUnknownKeys = false) + { + $map = [ + 'item' => ['names' => [CallHierarchyItem::class], 'iterable' => false], + 'workDoneToken' => ['names' => [], 'iterable' => false], + 'partialResultToken' => ['names' => [], 'iterable' => false], + ]; + + foreach ($array as $key => &$value) { + if (!isset($map[$key])) { + if ($allowUnknownKeys) { + unset($array[$key]); + continue; + } + + throw new RuntimeException(sprintf( + 'Parameter "%s" on class "%s" not known, known parameters: "%s"', + $key, + self::class, + implode('", "', array_keys($map)) + )); + } + + // from here we only care about arrays that can be transformed into + // objects + if (!is_array($value)) { + continue; + } + + if (empty($map[$key]['names'])) { + continue; + } + + if ($map[$key]['iterable']) { + $value = array_map(function ($object) use ($map, $key, $allowUnknownKeys) { + if (!is_array($object)) { + return $object; + } + + return self::invokeFromNames($map[$key]['names'], $object, $allowUnknownKeys) ?: $object; + }, $value); + continue; + } + + $names = $map[$key]['names']; + $value = self::invokeFromNames($names, $value, $allowUnknownKeys) ?: $value; + } + + return Invoke::new(self::class, $array); + } + + /** + * @param array $classNames + * @param array $object + */ + private static function invokeFromNames(array $classNames, array $object, bool $allowUnknownKeys): ?object + { + $lastException = null; + foreach ($classNames as $className) { + try { + // @phpstan-ignore-next-line + return call_user_func_array($className . '::fromArray', [$object, $allowUnknownKeys]); + } catch (Exception $exception) { + $lastException = $exception; + continue; + } + } + + throw $lastException; + } + +} \ No newline at end of file diff --git a/src/CallHierarchyOutgoingCallsRequest.php b/src/CallHierarchyOutgoingCallsRequest.php new file mode 100644 index 0000000..8e44f35 --- /dev/null +++ b/src/CallHierarchyOutgoingCallsRequest.php @@ -0,0 +1,8 @@ +textDocument = $textDocument; + $this->position = $position; + $this->workDoneToken = $workDoneToken; + } + + /** + * @param array $array + * @return self + */ + public static function fromArray(array $array, bool $allowUnknownKeys = false) + { + $map = [ + 'textDocument' => ['names' => [TextDocumentIdentifier::class], 'iterable' => false], + 'position' => ['names' => [Position::class], 'iterable' => false], + 'workDoneToken' => ['names' => [], 'iterable' => false], + ]; + + foreach ($array as $key => &$value) { + if (!isset($map[$key])) { + if ($allowUnknownKeys) { + unset($array[$key]); + continue; + } + + throw new RuntimeException(sprintf( + 'Parameter "%s" on class "%s" not known, known parameters: "%s"', + $key, + self::class, + implode('", "', array_keys($map)) + )); + } + + // from here we only care about arrays that can be transformed into + // objects + if (!is_array($value)) { + continue; + } + + if (empty($map[$key]['names'])) { + continue; + } + + if ($map[$key]['iterable']) { + $value = array_map(function ($object) use ($map, $key, $allowUnknownKeys) { + if (!is_array($object)) { + return $object; + } + + return self::invokeFromNames($map[$key]['names'], $object, $allowUnknownKeys) ?: $object; + }, $value); + continue; + } + + $names = $map[$key]['names']; + $value = self::invokeFromNames($names, $value, $allowUnknownKeys) ?: $value; + } + + return Invoke::new(self::class, $array); + } + + /** + * @param array $classNames + * @param array $object + */ + private static function invokeFromNames(array $classNames, array $object, bool $allowUnknownKeys): ?object + { + $lastException = null; + foreach ($classNames as $className) { + try { + // @phpstan-ignore-next-line + return call_user_func_array($className . '::fromArray', [$object, $allowUnknownKeys]); + } catch (Exception $exception) { + $lastException = $exception; + continue; + } + } + + throw $lastException; + } + +} \ No newline at end of file diff --git a/src/CallHierarchyPrepareRequest.php b/src/CallHierarchyPrepareRequest.php new file mode 100644 index 0000000..7e0ceaa --- /dev/null +++ b/src/CallHierarchyPrepareRequest.php @@ -0,0 +1,8 @@ +|null + */ + public $documentSelector; + + /** + * + * @var bool|null + */ + public $workDoneProgress; + + /** + * The id used to register the request. The id can be used to deregister + * the request again. See also Registration#id. + * + * @var string|null + */ + public $id; + + /** + * @param array<(string|array{language:string,scheme:string,pattern:string}|array{language:string,scheme:string,pattern:string}|array{language:string,scheme:string,pattern:string}|array{notebook:string|array{notebookType:string,scheme:string,pattern:string}|array{notebookType:string,scheme:string,pattern:string}|array{notebookType:string,scheme:string,pattern:string},language:string})>|null $documentSelector + * @param bool|null $workDoneProgress + * @param string|null $id + */ + public function __construct($documentSelector = null, ?bool $workDoneProgress = null, ?string $id = null) + { + $this->documentSelector = $documentSelector; + $this->workDoneProgress = $workDoneProgress; + $this->id = $id; + } + + /** + * @param array $array + * @return self + */ + public static function fromArray(array $array, bool $allowUnknownKeys = false) + { + $map = [ + 'documentSelector' => ['names' => [], 'iterable' => false], + 'workDoneProgress' => ['names' => [], 'iterable' => false], + 'id' => ['names' => [], 'iterable' => false], + ]; + + foreach ($array as $key => &$value) { + if (!isset($map[$key])) { + if ($allowUnknownKeys) { + unset($array[$key]); + continue; + } + + throw new RuntimeException(sprintf( + 'Parameter "%s" on class "%s" not known, known parameters: "%s"', + $key, + self::class, + implode('", "', array_keys($map)) + )); + } + + // from here we only care about arrays that can be transformed into + // objects + if (!is_array($value)) { + continue; + } + + if (empty($map[$key]['names'])) { + continue; + } + + if ($map[$key]['iterable']) { + $value = array_map(function ($object) use ($map, $key, $allowUnknownKeys) { + if (!is_array($object)) { + return $object; + } + + return self::invokeFromNames($map[$key]['names'], $object, $allowUnknownKeys) ?: $object; + }, $value); + continue; + } + + $names = $map[$key]['names']; + $value = self::invokeFromNames($names, $value, $allowUnknownKeys) ?: $value; + } + + return Invoke::new(self::class, $array); + } + + /** + * @param array $classNames + * @param array $object + */ + private static function invokeFromNames(array $classNames, array $object, bool $allowUnknownKeys): ?object + { + $lastException = null; + foreach ($classNames as $className) { + try { + // @phpstan-ignore-next-line + return call_user_func_array($className . '::fromArray', [$object, $allowUnknownKeys]); + } catch (Exception $exception) { + $lastException = $exception; + continue; + } + } + + throw $lastException; + } + +} \ No newline at end of file diff --git a/src/ServerCapabilities.php b/src/ServerCapabilities.php index 866edba..7d61d6d 100644 --- a/src/ServerCapabilities.php +++ b/src/ServerCapabilities.php @@ -202,7 +202,7 @@ class ServerCapabilities /** * The server provides call hierarchy support. * - * @var bool|mixed|mixed|null + * @var bool|CallHierarchyOptions|CallHierarchyRegistrationOptions|null */ public $callHierarchyProvider; @@ -295,7 +295,7 @@ class ServerCapabilities * @param bool|FoldingRangeOptions|FoldingRangeRegistrationOptions|null $foldingRangeProvider * @param bool|SelectionRangeOptions|SelectionRangeRegistrationOptions|null $selectionRangeProvider * @param ExecuteCommandOptions|null $executeCommandProvider - * @param bool|mixed|mixed|null $callHierarchyProvider + * @param bool|CallHierarchyOptions|CallHierarchyRegistrationOptions|null $callHierarchyProvider * @param bool|mixed|mixed|null $linkedEditingRangeProvider * @param mixed|mixed|null $semanticTokensProvider * @param bool|mixed|mixed|null $monikerProvider @@ -377,7 +377,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false) 'foldingRangeProvider' => ['names' => [FoldingRangeOptions::class, FoldingRangeRegistrationOptions::class], 'iterable' => false], 'selectionRangeProvider' => ['names' => [SelectionRangeOptions::class, SelectionRangeRegistrationOptions::class], 'iterable' => false], 'executeCommandProvider' => ['names' => [ExecuteCommandOptions::class], 'iterable' => false], - 'callHierarchyProvider' => ['names' => [], 'iterable' => false], + 'callHierarchyProvider' => ['names' => [CallHierarchyOptions::class, CallHierarchyRegistrationOptions::class], 'iterable' => false], 'linkedEditingRangeProvider' => ['names' => [], 'iterable' => false], 'semanticTokensProvider' => ['names' => [], 'iterable' => false], 'monikerProvider' => ['names' => [], 'iterable' => false], diff --git a/src/TextDocumentClientCapabilities.php b/src/TextDocumentClientCapabilities.php index 2683f38..8b06fc9 100644 --- a/src/TextDocumentClientCapabilities.php +++ b/src/TextDocumentClientCapabilities.php @@ -169,7 +169,7 @@ class TextDocumentClientCapabilities /** * Capabilities specific to the various call hierarchy requests. * - * @var mixed|null + * @var CallHierarchyClientCapabilities|null */ public $callHierarchy; @@ -245,7 +245,7 @@ class TextDocumentClientCapabilities * @param FoldingRangeClientCapabilities|null $foldingRange * @param SelectionRangeClientCapabilities|null $selectionRange * @param PublishDiagnosticsClientCapabilities|null $publishDiagnostics - * @param mixed|null $callHierarchy + * @param CallHierarchyClientCapabilities|null $callHierarchy * @param mixed|null $semanticTokens * @param mixed|null $linkedEditingRange * @param mixed|null $moniker @@ -254,7 +254,7 @@ class TextDocumentClientCapabilities * @param array{dynamicRegistration:bool,resolveSupport:array{properties:array}}|null $inlayHint * @param mixed|null $diagnostic */ - public function __construct(?TextDocumentSyncClientCapabilities $synchronization = null, ?CompletionClientCapabilities $completion = null, ?HoverClientCapabilities $hover = null, ?SignatureHelpClientCapabilities $signatureHelp = null, ?DeclarationClientCapabilities $declaration = null, ?DefinitionClientCapabilities $definition = null, ?TypeDefinitionClientCapabilities $typeDefinition = null, ?ImplementationClientCapabilities $implementation = null, ?ReferenceClientCapabilities $references = null, ?DocumentHighlightClientCapabilities $documentHighlight = null, ?DocumentSymbolClientCapabilities $documentSymbol = null, ?CodeActionClientCapabilities $codeAction = null, ?CodeLensClientCapabilities $codeLens = null, ?DocumentLinkClientCapabilities $documentLink = null, ?DocumentColorClientCapabilities $colorProvider = null, ?DocumentFormattingClientCapabilities $formatting = null, ?DocumentRangeFormattingClientCapabilities $rangeFormatting = null, ?DocumentOnTypeFormattingClientCapabilities $onTypeFormatting = null, ?RenameClientCapabilities $rename = null, ?FoldingRangeClientCapabilities $foldingRange = null, ?SelectionRangeClientCapabilities $selectionRange = null, ?PublishDiagnosticsClientCapabilities $publishDiagnostics = null, $callHierarchy = null, $semanticTokens = null, $linkedEditingRange = null, $moniker = null, $typeHierarchy = null, ?array $inlineValue = null, ?array $inlayHint = null, $diagnostic = null) + public function __construct(?TextDocumentSyncClientCapabilities $synchronization = null, ?CompletionClientCapabilities $completion = null, ?HoverClientCapabilities $hover = null, ?SignatureHelpClientCapabilities $signatureHelp = null, ?DeclarationClientCapabilities $declaration = null, ?DefinitionClientCapabilities $definition = null, ?TypeDefinitionClientCapabilities $typeDefinition = null, ?ImplementationClientCapabilities $implementation = null, ?ReferenceClientCapabilities $references = null, ?DocumentHighlightClientCapabilities $documentHighlight = null, ?DocumentSymbolClientCapabilities $documentSymbol = null, ?CodeActionClientCapabilities $codeAction = null, ?CodeLensClientCapabilities $codeLens = null, ?DocumentLinkClientCapabilities $documentLink = null, ?DocumentColorClientCapabilities $colorProvider = null, ?DocumentFormattingClientCapabilities $formatting = null, ?DocumentRangeFormattingClientCapabilities $rangeFormatting = null, ?DocumentOnTypeFormattingClientCapabilities $onTypeFormatting = null, ?RenameClientCapabilities $rename = null, ?FoldingRangeClientCapabilities $foldingRange = null, ?SelectionRangeClientCapabilities $selectionRange = null, ?PublishDiagnosticsClientCapabilities $publishDiagnostics = null, ?CallHierarchyClientCapabilities $callHierarchy = null, $semanticTokens = null, $linkedEditingRange = null, $moniker = null, $typeHierarchy = null, ?array $inlineValue = null, ?array $inlayHint = null, $diagnostic = null) { $this->synchronization = $synchronization; $this->completion = $completion; @@ -317,7 +317,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false) 'foldingRange' => ['names' => [FoldingRangeClientCapabilities::class], 'iterable' => false], 'selectionRange' => ['names' => [SelectionRangeClientCapabilities::class], 'iterable' => false], 'publishDiagnostics' => ['names' => [PublishDiagnosticsClientCapabilities::class], 'iterable' => false], - 'callHierarchy' => ['names' => [], 'iterable' => false], + 'callHierarchy' => ['names' => [CallHierarchyClientCapabilities::class], 'iterable' => false], 'semanticTokens' => ['names' => [], 'iterable' => false], 'linkedEditingRange' => ['names' => [], 'iterable' => false], 'moniker' => ['names' => [], 'iterable' => false], diff --git a/tests/Unit/CallHierarchyIncomingCallsParamsTest.php b/tests/Unit/CallHierarchyIncomingCallsParamsTest.php new file mode 100644 index 0000000..6eb3bb6 --- /dev/null +++ b/tests/Unit/CallHierarchyIncomingCallsParamsTest.php @@ -0,0 +1,57 @@ + [ + 'name' => 'processMessages', + 'kind' => SymbolKind::METHOD, + 'uri' => 'file:///path/to/file.php', + 'range' => [ + 'start' => ['line' => 10, 'character' => 4], + 'end' => ['line' => 12, 'character' => 0], + ], + 'selectionRange' => [ + 'start' => ['line' => 10, 'character' => 4], + 'end' => ['line' => 10, 'character' => 20], + ], + 'detail' => 'MyClass', + ], + ]); + + self::assertEquals($expected, $params); + } +} diff --git a/ts/transpile.ts b/ts/transpile.ts index 14a0a20..a4c1b8c 100644 --- a/ts/transpile.ts +++ b/ts/transpile.ts @@ -22,6 +22,7 @@ const paths: string[] = [ path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.selectionRange.d.ts'), path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.inlayHint.d.ts'), path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.inlineValue.d.ts'), + path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.callHierarchy.d.ts'), path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-types', 'lib', 'umd', 'main.d.ts'), path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-types', 'lib', 'esm', 'main.d.ts'), path.resolve(__dirname, '../ts/stubs.ts'),