diff --git a/src/AnnotatedTextEdit.php b/src/AnnotatedTextEdit.php
new file mode 100644
index 0000000..fd52896
--- /dev/null
+++ b/src/AnnotatedTextEdit.php
@@ -0,0 +1,126 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * A special text edit with an additional change annotation.
+ *
+ * Mixins (implemented TS interfaces): TextEdit
+ */
+class AnnotatedTextEdit extends TextEdit
+{
+    /**
+     * The actual identifier of the change annotation
+     *
+     * @var string
+     */
+    public $annotationId;
+
+    /**
+     * The range of the text document to be manipulated. To insert
+     * text into a document create a range where start === end.
+     *
+     * @var Range
+     */
+    public $range;
+
+    /**
+     * The string to be inserted. For delete operations use an
+     * empty string.
+     *
+     * @var string
+     */
+    public $newText;
+
+    /**
+     * @param string $annotationId
+     * @param Range $range
+     * @param string $newText
+     */
+    public function __construct(string $annotationId, Range $range, string $newText)
+    {
+        $this->annotationId = $annotationId;
+        $this->range = $range;
+        $this->newText = $newText;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'annotationId' => ['names' => [], 'iterable' => false],
+            'range' => ['names' => [Range::class], 'iterable' => false],
+            'newText' => ['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<string> $classNames
+     * @param array<string,mixed> $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/CallHierarchyClientCapabilities.php b/src/CallHierarchyClientCapabilities.php
new file mode 100644
index 0000000..7c4e8ff
--- /dev/null
+++ b/src/CallHierarchyClientCapabilities.php
@@ -0,0 +1,103 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ */
+class CallHierarchyClientCapabilities
+{
+    /**
+     * Whether implementation supports dynamic registration. If this is set to `true`
+     * the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
+     * return value for the corresponding server capability as well.
+     *
+     * @var bool|null
+     */
+    public $dynamicRegistration;
+
+    /**
+     * @param bool|null $dynamicRegistration
+     */
+    public function __construct(?bool $dynamicRegistration = null)
+    {
+        $this->dynamicRegistration = $dynamicRegistration;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    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<string> $classNames
+     * @param array<string,mixed> $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/CallHierarchyIncomingCall.php b/src/CallHierarchyIncomingCall.php
new file mode 100644
index 0000000..d3783cb
--- /dev/null
+++ b/src/CallHierarchyIncomingCall.php
@@ -0,0 +1,113 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Represents an incoming call, e.g. a caller of a method or constructor.
+ */
+class CallHierarchyIncomingCall
+{
+    /**
+     * The item that makes the call.
+     *
+     * @var CallHierarchyItem
+     */
+    public $from;
+
+    /**
+     * The ranges at which the calls appear. This is relative to the caller
+     * denoted by [`this.from`](#CallHierarchyIncomingCall.from).
+     *
+     * @var array<Range>
+     */
+    public $fromRanges;
+
+    /**
+     * @param CallHierarchyItem $from
+     * @param array<Range> $fromRanges
+     */
+    public function __construct(CallHierarchyItem $from, array $fromRanges)
+    {
+        $this->from = $from;
+        $this->fromRanges = $fromRanges;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'from' => ['names' => [CallHierarchyItem::class], 'iterable' => false],
+            'fromRanges' => ['names' => [Range::class], 'iterable' => true],
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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..46f0e29
--- /dev/null
+++ b/src/CallHierarchyIncomingCallsParams.php
@@ -0,0 +1,124 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * The parameter of a `callHierarchy/incomingCalls` request.
+ *
+ * Mixins (implemented TS interfaces): WorkDoneProgressParams, PartialResultParams
+ */
+class CallHierarchyIncomingCallsParams extends WorkDoneProgressParams
+{
+    /**
+     *
+     * @var CallHierarchyItem
+     */
+    public $item;
+
+    /**
+     * An optional token that a server can use to report work done progress.
+     *
+     * @var int|string|null
+     */
+    public $workDoneToken;
+
+    /**
+     * An optional token that a server can use to report partial results (e.g. streaming) to
+     * the client.
+     *
+     * @var int|string|null
+     */
+    public $partialResultToken;
+
+    /**
+     * @param CallHierarchyItem $item
+     * @param int|string|null $workDoneToken
+     * @param int|string|null $partialResultToken
+     */
+    public function __construct(CallHierarchyItem $item, $workDoneToken = null, $partialResultToken = null)
+    {
+        $this->item = $item;
+        $this->workDoneToken = $workDoneToken;
+        $this->partialResultToken = $partialResultToken;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    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<string> $classNames
+     * @param array<string,mixed> $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 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface CallHierarchyIncomingCallsRequest
+{
+    public const METHOD = 'callHierarchy/incomingCalls';
+}
\ No newline at end of file
diff --git a/src/CallHierarchyItem.php b/src/CallHierarchyItem.php
new file mode 100644
index 0000000..1b8ee9c
--- /dev/null
+++ b/src/CallHierarchyItem.php
@@ -0,0 +1,175 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Represents programming constructs like functions or constructors in the context
+ * of call hierarchy.
+ */
+class CallHierarchyItem
+{
+    /**
+     * The name of this item.
+     *
+     * @var string
+     */
+    public $name;
+
+    /**
+     * The kind of this item.
+     *
+     * @var SymbolKind::*
+     */
+    public $kind;
+
+    /**
+     * Tags for this item.
+     *
+     * @var array<SymbolTag::*>|null
+     */
+    public $tags;
+
+    /**
+     * More detail for this item, e.g. the signature of a function.
+     *
+     * @var string|null
+     */
+    public $detail;
+
+    /**
+     * The resource identifier of this item.
+     *
+     * @var string
+     */
+    public $uri;
+
+    /**
+     * The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code.
+     *
+     * @var Range
+     */
+    public $range;
+
+    /**
+     * The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function.
+     * Must be contained by the [`range`](#CallHierarchyItem.range).
+     *
+     * @var Range
+     */
+    public $selectionRange;
+
+    /**
+     * A data entry field that is preserved between a call hierarchy prepare and
+     * incoming calls or outgoing calls requests.
+     *
+     * @var |null
+     */
+    public $data;
+
+    /**
+     * @param string $name
+     * @param SymbolKind::* $kind
+     * @param array<SymbolTag::*>|null $tags
+     * @param string|null $detail
+     * @param string $uri
+     * @param Range $range
+     * @param Range $selectionRange
+     * @param |null $data
+     */
+    public function __construct(string $name, $kind, string $uri, Range $range, Range $selectionRange, ?array $tags = null, ?string $detail = null, $data = null)
+    {
+        $this->name = $name;
+        $this->kind = $kind;
+        $this->tags = $tags;
+        $this->detail = $detail;
+        $this->uri = $uri;
+        $this->range = $range;
+        $this->selectionRange = $selectionRange;
+        $this->data = $data;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'name' => ['names' => [], 'iterable' => false],
+            'kind' => ['names' => [], 'iterable' => false],
+            'tags' => ['names' => [], 'iterable' => true],
+            'detail' => ['names' => [], 'iterable' => false],
+            'uri' => ['names' => [], 'iterable' => false],
+            'range' => ['names' => [Range::class], 'iterable' => false],
+            'selectionRange' => ['names' => [Range::class], 'iterable' => false],
+            'data' => ['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<string> $classNames
+     * @param array<string,mixed> $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/CallHierarchyOptions.php b/src/CallHierarchyOptions.php
new file mode 100644
index 0000000..971361b
--- /dev/null
+++ b/src/CallHierarchyOptions.php
@@ -0,0 +1,103 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Call hierarchy options used during static registration.
+ *
+ * Mixins (implemented TS interfaces): WorkDoneProgressOptions
+ */
+class CallHierarchyOptions extends WorkDoneProgressOptions
+{
+    /**
+     *
+     * @var bool|null
+     */
+    public $workDoneProgress;
+
+    /**
+     * @param bool|null $workDoneProgress
+     */
+    public function __construct(?bool $workDoneProgress = null)
+    {
+        $this->workDoneProgress = $workDoneProgress;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    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<string> $classNames
+     * @param array<string,mixed> $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/CallHierarchyOutgoingCall.php b/src/CallHierarchyOutgoingCall.php
new file mode 100644
index 0000000..dcb2b9b
--- /dev/null
+++ b/src/CallHierarchyOutgoingCall.php
@@ -0,0 +1,114 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc.
+ */
+class CallHierarchyOutgoingCall
+{
+    /**
+     * The item that is called.
+     *
+     * @var CallHierarchyItem
+     */
+    public $to;
+
+    /**
+     * The range at which this item is called. This is the range relative to the caller, e.g the item
+     * passed to [`provideCallHierarchyOutgoingCalls`](#CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls)
+     * and not [`this.to`](#CallHierarchyOutgoingCall.to).
+     *
+     * @var array<Range>
+     */
+    public $fromRanges;
+
+    /**
+     * @param CallHierarchyItem $to
+     * @param array<Range> $fromRanges
+     */
+    public function __construct(CallHierarchyItem $to, array $fromRanges)
+    {
+        $this->to = $to;
+        $this->fromRanges = $fromRanges;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'to' => ['names' => [CallHierarchyItem::class], 'iterable' => false],
+            'fromRanges' => ['names' => [Range::class], 'iterable' => true],
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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..8ca3e3d
--- /dev/null
+++ b/src/CallHierarchyOutgoingCallsParams.php
@@ -0,0 +1,124 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * The parameter of a `callHierarchy/outgoingCalls` request.
+ *
+ * Mixins (implemented TS interfaces): WorkDoneProgressParams, PartialResultParams
+ */
+class CallHierarchyOutgoingCallsParams extends WorkDoneProgressParams
+{
+    /**
+     *
+     * @var CallHierarchyItem
+     */
+    public $item;
+
+    /**
+     * An optional token that a server can use to report work done progress.
+     *
+     * @var int|string|null
+     */
+    public $workDoneToken;
+
+    /**
+     * An optional token that a server can use to report partial results (e.g. streaming) to
+     * the client.
+     *
+     * @var int|string|null
+     */
+    public $partialResultToken;
+
+    /**
+     * @param CallHierarchyItem $item
+     * @param int|string|null $workDoneToken
+     * @param int|string|null $partialResultToken
+     */
+    public function __construct(CallHierarchyItem $item, $workDoneToken = null, $partialResultToken = null)
+    {
+        $this->item = $item;
+        $this->workDoneToken = $workDoneToken;
+        $this->partialResultToken = $partialResultToken;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    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<string> $classNames
+     * @param array<string,mixed> $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 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface CallHierarchyOutgoingCallsRequest
+{
+    public const METHOD = 'callHierarchy/outgoingCalls';
+}
\ No newline at end of file
diff --git a/src/CallHierarchyPrepareParams.php b/src/CallHierarchyPrepareParams.php
new file mode 100644
index 0000000..3065b97
--- /dev/null
+++ b/src/CallHierarchyPrepareParams.php
@@ -0,0 +1,124 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * The parameter of a `textDocument/prepareCallHierarchy` request.
+ *
+ * Mixins (implemented TS interfaces): TextDocumentPositionParams, WorkDoneProgressParams
+ */
+class CallHierarchyPrepareParams extends TextDocumentPositionParams
+{
+    /**
+     * The text document.
+     *
+     * @var TextDocumentIdentifier
+     */
+    public $textDocument;
+
+    /**
+     * The position inside the text document.
+     *
+     * @var Position
+     */
+    public $position;
+
+    /**
+     * An optional token that a server can use to report work done progress.
+     *
+     * @var int|string|null
+     */
+    public $workDoneToken;
+
+    /**
+     * @param TextDocumentIdentifier $textDocument
+     * @param Position $position
+     * @param int|string|null $workDoneToken
+     */
+    public function __construct(TextDocumentIdentifier $textDocument, Position $position, $workDoneToken = null)
+    {
+        $this->textDocument = $textDocument;
+        $this->position = $position;
+        $this->workDoneToken = $workDoneToken;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    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<string> $classNames
+     * @param array<string,mixed> $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 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface CallHierarchyPrepareRequest
+{
+    public const METHOD = 'textDocument/prepareCallHierarchy';
+}
\ No newline at end of file
diff --git a/src/CallHierarchyRegistrationOptions.php b/src/CallHierarchyRegistrationOptions.php
new file mode 100644
index 0000000..f1ed48d
--- /dev/null
+++ b/src/CallHierarchyRegistrationOptions.php
@@ -0,0 +1,125 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Call hierarchy options used during static or dynamic registration.
+ *
+ * Mixins (implemented TS interfaces): TextDocumentRegistrationOptions, CallHierarchyOptions, StaticRegistrationOptions
+ */
+class CallHierarchyRegistrationOptions extends TextDocumentRegistrationOptions
+{
+    /**
+     * A document selector to identify the scope of the registration. If set to null
+     * the document selector provided on the client side will be used.
+     *
+     * @var array<(string|array<mixed>|array<mixed>|array<mixed>)>|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<mixed>|array<mixed>|array<mixed>)>|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<string,mixed> $array
+     * @return static
+     */
+    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<string> $classNames
+     * @param array<string,mixed> $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/ChangeAnnotation.php b/src/ChangeAnnotation.php
new file mode 100644
index 0000000..c8d9493
--- /dev/null
+++ b/src/ChangeAnnotation.php
@@ -0,0 +1,125 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Additional information that describes document changes.
+ */
+class ChangeAnnotation
+{
+    /**
+     * A human-readable string describing the actual change. The string
+     * is rendered prominent in the user interface.
+     *
+     * @var string
+     */
+    public $label;
+
+    /**
+     * A flag which indicates that user confirmation is needed
+     * before applying the change.
+     *
+     * @var bool|null
+     */
+    public $needsConfirmation;
+
+    /**
+     * A human-readable string which is rendered less prominent in
+     * the user interface.
+     *
+     * @var string|null
+     */
+    public $description;
+
+    /**
+     * @param string $label
+     * @param bool|null $needsConfirmation
+     * @param string|null $description
+     */
+    public function __construct(string $label, ?bool $needsConfirmation = null, ?string $description = null)
+    {
+        $this->label = $label;
+        $this->needsConfirmation = $needsConfirmation;
+        $this->description = $description;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'label' => ['names' => [], 'iterable' => false],
+            'needsConfirmation' => ['names' => [], 'iterable' => false],
+            'description' => ['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<string> $classNames
+     * @param array<string,mixed> $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/ClientCapabilities.php b/src/ClientCapabilities.php
index 3a98c27..e702151 100644
--- a/src/ClientCapabilities.php
+++ b/src/ClientCapabilities.php
@@ -32,6 +32,13 @@ class ClientCapabilities
      */
     public $window;
 
+    /**
+     * General client capabilities.
+     *
+     * @var GeneralClientCapabilities|null
+     */
+    public $general;
+
     /**
      * Experimental client capabilities.
      *
@@ -43,13 +50,15 @@ class ClientCapabilities
      * @param array<mixed>|null $workspace
      * @param TextDocumentClientCapabilities|null $textDocument
      * @param array<mixed>|null $window
+     * @param GeneralClientCapabilities|null $general
      * @param array<mixed>|null $experimental
      */
-    public function __construct(?array $workspace = null, ?TextDocumentClientCapabilities $textDocument = null, ?array $window = null, ?array $experimental = null)
+    public function __construct(?array $workspace = null, ?TextDocumentClientCapabilities $textDocument = null, ?array $window = null, ?GeneralClientCapabilities $general = null, ?array $experimental = null)
     {
         $this->workspace = $workspace;
         $this->textDocument = $textDocument;
         $this->window = $window;
+        $this->general = $general;
         $this->experimental = $experimental;
     }
 
@@ -63,6 +72,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'workspace' => ['names' => [], 'iterable' => false],
             'textDocument' => ['names' => [TextDocumentClientCapabilities::class], 'iterable' => false],
             'window' => ['names' => [], 'iterable' => false],
+            'general' => ['names' => [GeneralClientCapabilities::class], 'iterable' => false],
             'experimental' => ['names' => [], 'iterable' => false],
         ];
 
diff --git a/src/CodeAction.php b/src/CodeAction.php
index acdc457..8198016 100644
--- a/src/CodeAction.php
+++ b/src/CodeAction.php
@@ -48,6 +48,25 @@ class CodeAction
      */
     public $isPreferred;
 
+    /**
+     * Marks that the code action cannot currently be applied.
+     * 
+     * Clients should follow the following guidelines regarding disabled code actions:
+     * 
+     *    - Disabled code actions are not shown in automatic [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action)
+     *      code action menu.
+     * 
+     *    - Disabled actions are shown as faded out in the code action menu when the user request a more specific type
+     *      of code action, such as refactorings.
+     * 
+     *    - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions)
+     *      that auto applies a code action and only a disabled code actions are returned, the client should show the user an
+     *      error message with `reason` in the editor.
+     *
+     * @var array<mixed>|null
+     */
+    public $disabled;
+
     /**
      * The workspace edit this code action performs.
      *
@@ -64,22 +83,34 @@ class CodeAction
      */
     public $command;
 
+    /**
+     * A data entry field that is preserved on a code action between
+     * a `textDocument/codeAction` and a `codeAction/resolve` request.
+     *
+     * @var |null
+     */
+    public $data;
+
     /**
      * @param string $title
      * @param string|null $kind
      * @param array<Diagnostic>|null $diagnostics
      * @param bool|null $isPreferred
+     * @param array<mixed>|null $disabled
      * @param WorkspaceEdit|null $edit
      * @param Command|null $command
+     * @param |null $data
      */
-    public function __construct(string $title, ?string $kind = null, ?array $diagnostics = null, ?bool $isPreferred = null, ?WorkspaceEdit $edit = null, ?Command $command = null)
+    public function __construct(string $title, ?string $kind = null, ?array $diagnostics = null, ?bool $isPreferred = null, ?array $disabled = null, ?WorkspaceEdit $edit = null, ?Command $command = null, $data = null)
     {
         $this->title = $title;
         $this->kind = $kind;
         $this->diagnostics = $diagnostics;
         $this->isPreferred = $isPreferred;
+        $this->disabled = $disabled;
         $this->edit = $edit;
         $this->command = $command;
+        $this->data = $data;
     }
 
     /**
@@ -93,8 +124,10 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'kind' => ['names' => [], 'iterable' => false],
             'diagnostics' => ['names' => [Diagnostic::class], 'iterable' => true],
             'isPreferred' => ['names' => [], 'iterable' => false],
+            'disabled' => ['names' => [], 'iterable' => false],
             'edit' => ['names' => [WorkspaceEdit::class], 'iterable' => false],
             'command' => ['names' => [Command::class], 'iterable' => false],
+            'data' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/CodeActionClientCapabilities.php b/src/CodeActionClientCapabilities.php
index 6b7d7ca..be60748 100644
--- a/src/CodeActionClientCapabilities.php
+++ b/src/CodeActionClientCapabilities.php
@@ -19,8 +19,9 @@ class CodeActionClientCapabilities
     public $dynamicRegistration;
 
     /**
-     * The client support code action literals as a valid
-     * response of the `textDocument/codeAction` request.
+     * The client support code action literals of type `CodeAction` as a valid
+     * response of the `textDocument/codeAction` request. If the property is not
+     * set the request can only return `Command` literals.
      *
      * @var array<mixed>|null
      */
@@ -33,16 +34,59 @@ class CodeActionClientCapabilities
      */
     public $isPreferredSupport;
 
+    /**
+     * Whether code action supports the `disabled` property.
+     *
+     * @var bool|null
+     */
+    public $disabledSupport;
+
+    /**
+     * Whether code action supports the `data` property which is
+     * preserved between a `textDocument/codeAction` and a
+     * `codeAction/resolve` request.
+     *
+     * @var bool|null
+     */
+    public $dataSupport;
+
+    /**
+     * Whether the client support resolving additional code action
+     * properties via a separate `codeAction/resolve` request.
+     *
+     * @var array<mixed>|null
+     */
+    public $resolveSupport;
+
+    /**
+     * Whether th client honors the change annotations in
+     * text edits and resource operations returned via the
+     * `CodeAction#edit` property by for example presenting
+     * the workspace edit in the user interface and asking
+     * for confirmation.
+     *
+     * @var bool|null
+     */
+    public $honorsChangeAnnotations;
+
     /**
      * @param bool|null $dynamicRegistration
      * @param array<mixed>|null $codeActionLiteralSupport
      * @param bool|null $isPreferredSupport
+     * @param bool|null $disabledSupport
+     * @param bool|null $dataSupport
+     * @param array<mixed>|null $resolveSupport
+     * @param bool|null $honorsChangeAnnotations
      */
-    public function __construct(?bool $dynamicRegistration = null, ?array $codeActionLiteralSupport = null, ?bool $isPreferredSupport = null)
+    public function __construct(?bool $dynamicRegistration = null, ?array $codeActionLiteralSupport = null, ?bool $isPreferredSupport = null, ?bool $disabledSupport = null, ?bool $dataSupport = null, ?array $resolveSupport = null, ?bool $honorsChangeAnnotations = null)
     {
         $this->dynamicRegistration = $dynamicRegistration;
         $this->codeActionLiteralSupport = $codeActionLiteralSupport;
         $this->isPreferredSupport = $isPreferredSupport;
+        $this->disabledSupport = $disabledSupport;
+        $this->dataSupport = $dataSupport;
+        $this->resolveSupport = $resolveSupport;
+        $this->honorsChangeAnnotations = $honorsChangeAnnotations;
     }
 
     /**
@@ -55,6 +99,10 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'dynamicRegistration' => ['names' => [], 'iterable' => false],
             'codeActionLiteralSupport' => ['names' => [], 'iterable' => false],
             'isPreferredSupport' => ['names' => [], 'iterable' => false],
+            'disabledSupport' => ['names' => [], 'iterable' => false],
+            'dataSupport' => ['names' => [], 'iterable' => false],
+            'resolveSupport' => ['names' => [], 'iterable' => false],
+            'honorsChangeAnnotations' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/CodeActionContext.php b/src/CodeActionContext.php
index 3644008..8505704 100644
--- a/src/CodeActionContext.php
+++ b/src/CodeActionContext.php
@@ -14,7 +14,7 @@ class CodeActionContext
 {
     /**
      * An array of diagnostics known on the client side overlapping the range provided to the
-     * `textDocument/codeAction` request. They are provied so that the server knows which
+     * `textDocument/codeAction` request. They are provided so that the server knows which
      * errors are currently presented to the user for the given range. There is no guarantee
      * that these accurately reflect the error state of the resource. The primary parameter
      * to compute code actions is the provided range.
diff --git a/src/CodeActionOptions.php b/src/CodeActionOptions.php
index bf3d72a..74ca98e 100644
--- a/src/CodeActionOptions.php
+++ b/src/CodeActionOptions.php
@@ -23,6 +23,14 @@ class CodeActionOptions extends WorkDoneProgressOptions
      */
     public $codeActionKinds;
 
+    /**
+     * The server provides support to resolve additional
+     * information for a code action.
+     *
+     * @var bool|null
+     */
+    public $resolveProvider;
+
     /**
      *
      * @var bool|null
@@ -31,11 +39,13 @@ class CodeActionOptions extends WorkDoneProgressOptions
 
     /**
      * @param array<string>|null $codeActionKinds
+     * @param bool|null $resolveProvider
      * @param bool|null $workDoneProgress
      */
-    public function __construct(?array $codeActionKinds = null, ?bool $workDoneProgress = null)
+    public function __construct(?array $codeActionKinds = null, ?bool $resolveProvider = null, ?bool $workDoneProgress = null)
     {
         $this->codeActionKinds = $codeActionKinds;
+        $this->resolveProvider = $resolveProvider;
         $this->workDoneProgress = $workDoneProgress;
     }
 
@@ -47,6 +57,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
     {
         $map = [
             'codeActionKinds' => ['names' => [], 'iterable' => true],
+            'resolveProvider' => ['names' => [], 'iterable' => false],
             'workDoneProgress' => ['names' => [], 'iterable' => false],
         ];
 
diff --git a/src/CodeActionRegistrationOptions.php b/src/CodeActionRegistrationOptions.php
index 0785932..a5fa555 100644
--- a/src/CodeActionRegistrationOptions.php
+++ b/src/CodeActionRegistrationOptions.php
@@ -31,6 +31,14 @@ class CodeActionRegistrationOptions extends TextDocumentRegistrationOptions
      */
     public $codeActionKinds;
 
+    /**
+     * The server provides support to resolve additional
+     * information for a code action.
+     *
+     * @var bool|null
+     */
+    public $resolveProvider;
+
     /**
      *
      * @var bool|null
@@ -40,12 +48,14 @@ class CodeActionRegistrationOptions extends TextDocumentRegistrationOptions
     /**
      * @param array<(string|array<mixed>|array<mixed>|array<mixed>)>|null $documentSelector
      * @param array<string>|null $codeActionKinds
+     * @param bool|null $resolveProvider
      * @param bool|null $workDoneProgress
      */
-    public function __construct($documentSelector = null, ?array $codeActionKinds = null, ?bool $workDoneProgress = null)
+    public function __construct($documentSelector = null, ?array $codeActionKinds = null, ?bool $resolveProvider = null, ?bool $workDoneProgress = null)
     {
         $this->documentSelector = $documentSelector;
         $this->codeActionKinds = $codeActionKinds;
+        $this->resolveProvider = $resolveProvider;
         $this->workDoneProgress = $workDoneProgress;
     }
 
@@ -58,6 +68,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
         $map = [
             'documentSelector' => ['names' => [], 'iterable' => false],
             'codeActionKinds' => ['names' => [], 'iterable' => true],
+            'resolveProvider' => ['names' => [], 'iterable' => false],
             'workDoneProgress' => ['names' => [], 'iterable' => false],
         ];
 
diff --git a/src/CodeActionResolveRequest.php b/src/CodeActionResolveRequest.php
new file mode 100644
index 0000000..bb06b93
--- /dev/null
+++ b/src/CodeActionResolveRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface CodeActionResolveRequest
+{
+    public const METHOD = 'codeAction/resolve';
+}
\ No newline at end of file
diff --git a/src/CodeDescription.php b/src/CodeDescription.php
new file mode 100644
index 0000000..b16fd21
--- /dev/null
+++ b/src/CodeDescription.php
@@ -0,0 +1,102 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Structure to capture a description for an error code.
+ */
+class CodeDescription
+{
+    /**
+     * An URI to open with more information about the diagnostic error.
+     *
+     * @var string
+     */
+    public $href;
+
+    /**
+     * @param string $href
+     */
+    public function __construct(string $href)
+    {
+        $this->href = $href;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'href' => ['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<string> $classNames
+     * @param array<string,mixed> $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/CodeLens.php b/src/CodeLens.php
index 2fb0a64..376f152 100644
--- a/src/CodeLens.php
+++ b/src/CodeLens.php
@@ -30,7 +30,7 @@ class CodeLens
     public $command;
 
     /**
-     * An data entry field that is preserved on a code lens item between
+     * A data entry field that is preserved on a code lens item between
      * a [CodeLensRequest](#CodeLensRequest) and a [CodeLensResolveRequest]
      * (#CodeLensResolveRequest)
      *
diff --git a/src/CodeLensRefreshRequest.php b/src/CodeLensRefreshRequest.php
new file mode 100644
index 0000000..187c397
--- /dev/null
+++ b/src/CodeLensRefreshRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface CodeLensRefreshRequest
+{
+    public const METHOD = `workspace/codeLens/refresh`;
+}
\ No newline at end of file
diff --git a/src/CodeLensRequest.php b/src/CodeLensRequest.php
new file mode 100644
index 0000000..7c66390
--- /dev/null
+++ b/src/CodeLensRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface CodeLensRequest
+{
+    public const METHOD = 'textDocument/codeLens';
+}
\ No newline at end of file
diff --git a/src/CodeLensResolveRequest.php b/src/CodeLensResolveRequest.php
new file mode 100644
index 0000000..0a8d6b7
--- /dev/null
+++ b/src/CodeLensResolveRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface CodeLensResolveRequest
+{
+    public const METHOD = 'codeLens/resolve';
+}
\ No newline at end of file
diff --git a/src/CodeLensWorkspaceClientCapabilities.php b/src/CodeLensWorkspaceClientCapabilities.php
new file mode 100644
index 0000000..0c7db10
--- /dev/null
+++ b/src/CodeLensWorkspaceClientCapabilities.php
@@ -0,0 +1,107 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ */
+class CodeLensWorkspaceClientCapabilities
+{
+    /**
+     * Whether the client implementation supports a refresh request sent from the
+     * server to the client.
+     * 
+     * Note that this event is global and will force the client to refresh all
+     * code lenses currently shown. It should be used with absolute care and is
+     * useful for situation where a server for example detect a project wide
+     * change that requires such a calculation.
+     *
+     * @var bool|null
+     */
+    public $refreshSupport;
+
+    /**
+     * @param bool|null $refreshSupport
+     */
+    public function __construct(?bool $refreshSupport = null)
+    {
+        $this->refreshSupport = $refreshSupport;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'refreshSupport' => ['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<string> $classNames
+     * @param array<string,mixed> $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/ColorInformation.php b/src/ColorInformation.php
index 2f6d7db..051581c 100644
--- a/src/ColorInformation.php
+++ b/src/ColorInformation.php
@@ -12,7 +12,7 @@
 class ColorInformation
 {
     /**
-     * The range in the document where this color appers.
+     * The range in the document where this color appears.
      *
      * @var Range
      */
diff --git a/src/CompletionClientCapabilities.php b/src/CompletionClientCapabilities.php
index 1d9d01f..ca66e6f 100644
--- a/src/CompletionClientCapabilities.php
+++ b/src/CompletionClientCapabilities.php
@@ -32,9 +32,18 @@ class CompletionClientCapabilities
      */
     public $completionItemKind;
 
+    /**
+     * Defines how the client handles whitespace and indentation
+     * when accepting a completion item that uses multi line
+     * text in either `insertText` or `textEdit`.
+     *
+     * @var InsertTextMode::*|null
+     */
+    public $insertTextMode;
+
     /**
      * The client supports to send additional context information for a
-     * `textDocument/completion` requestion.
+     * `textDocument/completion` request.
      *
      * @var bool|null
      */
@@ -44,13 +53,15 @@ class CompletionClientCapabilities
      * @param bool|null $dynamicRegistration
      * @param array<mixed>|null $completionItem
      * @param array<mixed>|null $completionItemKind
+     * @param InsertTextMode::*|null $insertTextMode
      * @param bool|null $contextSupport
      */
-    public function __construct(?bool $dynamicRegistration = null, ?array $completionItem = null, ?array $completionItemKind = null, ?bool $contextSupport = null)
+    public function __construct(?bool $dynamicRegistration = null, ?array $completionItem = null, ?array $completionItemKind = null, $insertTextMode = null, ?bool $contextSupport = null)
     {
         $this->dynamicRegistration = $dynamicRegistration;
         $this->completionItem = $completionItem;
         $this->completionItemKind = $completionItemKind;
+        $this->insertTextMode = $insertTextMode;
         $this->contextSupport = $contextSupport;
     }
 
@@ -64,6 +75,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'dynamicRegistration' => ['names' => [], 'iterable' => false],
             'completionItem' => ['names' => [], 'iterable' => false],
             'completionItemKind' => ['names' => [], 'iterable' => false],
+            'insertTextMode' => ['names' => [], 'iterable' => false],
             'contextSupport' => ['names' => [], 'iterable' => false],
         ];
 
diff --git a/src/CompletionItem.php b/src/CompletionItem.php
index 575f369..1455b21 100644
--- a/src/CompletionItem.php
+++ b/src/CompletionItem.php
@@ -105,22 +105,39 @@ class CompletionItem
 
     /**
      * The format of the insert text. The format applies to both the `insertText` property
-     * and the `newText` property of a provided `textEdit`. If ommitted defaults to
+     * and the `newText` property of a provided `textEdit`. If omitted defaults to
      * `InsertTextFormat.PlainText`.
      *
      * @var InsertTextFormat::*|null
      */
     public $insertTextFormat;
 
+    /**
+     * How whitespace and indentation is handled during completion
+     * item insertion. If ignored the clients default value depends on
+     * the `textDocument.completion.insertTextMode` client capability.
+     *
+     * @var InsertTextMode::*|null
+     */
+    public $insertTextMode;
+
     /**
      * An [edit](#TextEdit) which is applied to a document when selecting
      * this completion. When an edit is provided the value of
      * [insertText](#CompletionItem.insertText) is ignored.
      * 
-     * *Note:* The text edit's range must be a [single line] and it must contain the position
-     * at which completion has been requested.
+     * Most editors support two different operation when accepting a completion item. One is to insert a
+     * completion text and the other is to replace an existing text with a completion text. Since this can
+     * usually not predetermined by a server it can report both ranges. Clients need to signal support for
+     * `InsertReplaceEdits` via the `textDocument.completion.insertReplaceSupport` client capability
+     * property.
+     * 
+     * *Note 1:* The text edit's range as well as both ranges from a insert replace edit must be a
+     * [single line] and they must contain the position at which completion has been requested.
+     * *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range must be a prefix of
+     * the edit's replace range, that means it must be contained and starting at the same position.
      *
-     * @var TextEdit|null
+     * @var TextEdit|InsertReplaceEdit|null
      */
     public $textEdit;
 
@@ -156,7 +173,7 @@ class CompletionItem
     public $command;
 
     /**
-     * An data entry field that is preserved on a completion item between
+     * A data entry field that is preserved on a completion item between
      * a [CompletionRequest](#CompletionRequest) and a [CompletionResolveRequest]
      * (#CompletionResolveRequest)
      *
@@ -176,13 +193,14 @@ class CompletionItem
      * @param string|null $filterText
      * @param string|null $insertText
      * @param InsertTextFormat::*|null $insertTextFormat
-     * @param TextEdit|null $textEdit
+     * @param InsertTextMode::*|null $insertTextMode
+     * @param TextEdit|InsertReplaceEdit|null $textEdit
      * @param array<TextEdit>|null $additionalTextEdits
      * @param array<string>|null $commitCharacters
      * @param Command|null $command
      * @param mixed|null $data
      */
-    public function __construct(string $label, $kind = null, ?array $tags = null, ?string $detail = null, $documentation = null, ?bool $deprecated = null, ?bool $preselect = null, ?string $sortText = null, ?string $filterText = null, ?string $insertText = null, $insertTextFormat = null, ?TextEdit $textEdit = null, ?array $additionalTextEdits = null, ?array $commitCharacters = null, ?Command $command = null, $data = null)
+    public function __construct(string $label, $kind = null, ?array $tags = null, ?string $detail = null, $documentation = null, ?bool $deprecated = null, ?bool $preselect = null, ?string $sortText = null, ?string $filterText = null, ?string $insertText = null, $insertTextFormat = null, $insertTextMode = null, $textEdit = null, ?array $additionalTextEdits = null, ?array $commitCharacters = null, ?Command $command = null, $data = null)
     {
         $this->label = $label;
         $this->kind = $kind;
@@ -195,6 +213,7 @@ public function __construct(string $label, $kind = null, ?array $tags = null, ?s
         $this->filterText = $filterText;
         $this->insertText = $insertText;
         $this->insertTextFormat = $insertTextFormat;
+        $this->insertTextMode = $insertTextMode;
         $this->textEdit = $textEdit;
         $this->additionalTextEdits = $additionalTextEdits;
         $this->commitCharacters = $commitCharacters;
@@ -220,7 +239,8 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'filterText' => ['names' => [], 'iterable' => false],
             'insertText' => ['names' => [], 'iterable' => false],
             'insertTextFormat' => ['names' => [], 'iterable' => false],
-            'textEdit' => ['names' => [TextEdit::class], 'iterable' => false],
+            'insertTextMode' => ['names' => [], 'iterable' => false],
+            'textEdit' => ['names' => [TextEdit::class, InsertReplaceEdit::class], 'iterable' => false],
             'additionalTextEdits' => ['names' => [TextEdit::class], 'iterable' => true],
             'commitCharacters' => ['names' => [], 'iterable' => true],
             'command' => ['names' => [Command::class], 'iterable' => false],
diff --git a/src/CompletionOptions.php b/src/CompletionOptions.php
index 94b1dcd..40348ba 100644
--- a/src/CompletionOptions.php
+++ b/src/CompletionOptions.php
@@ -29,7 +29,7 @@ class CompletionOptions extends WorkDoneProgressOptions
 
     /**
      * The list of all possible characters that commit a completion. This field can be used
-     * if clients don't support individual commmit characters per completion item. See
+     * if clients don't support individual commit characters per completion item. See
      * `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport`
      * 
      * If a server provides both `allCommitCharacters` and commit characters on an individual
diff --git a/src/CompletionRegistrationOptions.php b/src/CompletionRegistrationOptions.php
index f932066..998fd8b 100644
--- a/src/CompletionRegistrationOptions.php
+++ b/src/CompletionRegistrationOptions.php
@@ -37,7 +37,7 @@ class CompletionRegistrationOptions extends TextDocumentRegistrationOptions
 
     /**
      * The list of all possible characters that commit a completion. This field can be used
-     * if clients don't support individual commmit characters per completion item. See
+     * if clients don't support individual commit characters per completion item. See
      * `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport`
      * 
      * If a server provides both `allCommitCharacters` and commit characters on an individual
diff --git a/src/CreateFile.php b/src/CreateFile.php
index e10cabd..84395fe 100644
--- a/src/CreateFile.php
+++ b/src/CreateFile.php
@@ -14,6 +14,7 @@
 class CreateFile extends ResourceOperation
 {
     /**
+     * The resource operation kind.
      *
      * @var string
      */
@@ -33,16 +34,25 @@ class CreateFile extends ResourceOperation
      */
     public $options;
 
+    /**
+     * An optional annotation identifier describing the operation.
+     *
+     * @var string|null
+     */
+    public $annotationId;
+
     /**
      * @param string $kind
      * @param string $uri
      * @param CreateFileOptions|null $options
+     * @param string|null $annotationId
      */
-    public function __construct(string $kind, string $uri, ?CreateFileOptions $options = null)
+    public function __construct(string $kind, string $uri, ?CreateFileOptions $options = null, ?string $annotationId = null)
     {
         $this->kind = $kind;
         $this->uri = $uri;
         $this->options = $options;
+        $this->annotationId = $annotationId;
     }
 
     /**
@@ -55,6 +65,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'kind' => ['names' => [], 'iterable' => false],
             'uri' => ['names' => [], 'iterable' => false],
             'options' => ['names' => [CreateFileOptions::class], 'iterable' => false],
+            'annotationId' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/CreateFilesParams.php b/src/CreateFilesParams.php
new file mode 100644
index 0000000..61fde72
--- /dev/null
+++ b/src/CreateFilesParams.php
@@ -0,0 +1,102 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * The parameters sent in file create requests/notifications.
+ */
+class CreateFilesParams
+{
+    /**
+     * An array of all files/folders created in this operation.
+     *
+     * @var array<FileCreate>
+     */
+    public $files;
+
+    /**
+     * @param array<FileCreate> $files
+     */
+    public function __construct(array $files)
+    {
+        $this->files = $files;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'files' => ['names' => [FileCreate::class], 'iterable' => true],
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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/DeclarationClientCapabilities.php b/src/DeclarationClientCapabilities.php
index 3e05583..05d130d 100644
--- a/src/DeclarationClientCapabilities.php
+++ b/src/DeclarationClientCapabilities.php
@@ -7,7 +7,6 @@
 use RuntimeException;
 
 /**
- * Since 3.14.0
  */
 class DeclarationClientCapabilities
 {
diff --git a/src/DeleteFile.php b/src/DeleteFile.php
index e12cb21..2910b47 100644
--- a/src/DeleteFile.php
+++ b/src/DeleteFile.php
@@ -14,6 +14,7 @@
 class DeleteFile extends ResourceOperation
 {
     /**
+     * The resource operation kind.
      *
      * @var string
      */
@@ -33,16 +34,25 @@ class DeleteFile extends ResourceOperation
      */
     public $options;
 
+    /**
+     * An optional annotation identifier describing the operation.
+     *
+     * @var string|null
+     */
+    public $annotationId;
+
     /**
      * @param string $kind
      * @param string $uri
      * @param DeleteFileOptions|null $options
+     * @param string|null $annotationId
      */
-    public function __construct(string $kind, string $uri, ?DeleteFileOptions $options = null)
+    public function __construct(string $kind, string $uri, ?DeleteFileOptions $options = null, ?string $annotationId = null)
     {
         $this->kind = $kind;
         $this->uri = $uri;
         $this->options = $options;
+        $this->annotationId = $annotationId;
     }
 
     /**
@@ -55,6 +65,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'kind' => ['names' => [], 'iterable' => false],
             'uri' => ['names' => [], 'iterable' => false],
             'options' => ['names' => [DeleteFileOptions::class], 'iterable' => false],
+            'annotationId' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/DeleteFilesParams.php b/src/DeleteFilesParams.php
new file mode 100644
index 0000000..cf30caf
--- /dev/null
+++ b/src/DeleteFilesParams.php
@@ -0,0 +1,102 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * The parameters sent in file delete requests/notifications.
+ */
+class DeleteFilesParams
+{
+    /**
+     * An array of all files/folders deleted in this operation.
+     *
+     * @var array<FileDelete>
+     */
+    public $files;
+
+    /**
+     * @param array<FileDelete> $files
+     */
+    public function __construct(array $files)
+    {
+        $this->files = $files;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'files' => ['names' => [FileDelete::class], 'iterable' => true],
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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/Diagnostic.php b/src/Diagnostic.php
index 2be30f9..d12bdd7 100644
--- a/src/Diagnostic.php
+++ b/src/Diagnostic.php
@@ -30,10 +30,17 @@ class Diagnostic
     /**
      * The diagnostic's code, which usually appear in the user interface.
      *
-     * @var int|string|null
+     * @var integer::*|string|null
      */
     public $code;
 
+    /**
+     * An optional property to describe the error code.
+     *
+     * @var CodeDescription|null
+     */
+    public $codeDescription;
+
     /**
      * A human-readable string describing the source of this
      * diagnostic, e.g. 'typescript' or 'super lint'. It usually
@@ -65,24 +72,36 @@ class Diagnostic
      */
     public $relatedInformation;
 
+    /**
+     * A data entry field that is preserved between a `textDocument/publishDiagnostics`
+     * notification and `textDocument/codeAction` request.
+     *
+     * @var |null
+     */
+    public $data;
+
     /**
      * @param Range $range
      * @param DiagnosticSeverity::*|null $severity
-     * @param int|string|null $code
+     * @param integer::*|string|null $code
+     * @param CodeDescription|null $codeDescription
      * @param string|null $source
      * @param string $message
      * @param array<DiagnosticTag::*>|null $tags
      * @param array<DiagnosticRelatedInformation>|null $relatedInformation
+     * @param |null $data
      */
-    public function __construct(Range $range, string $message, $severity = null, $code = null, ?string $source = null, ?array $tags = null, ?array $relatedInformation = null)
+    public function __construct(Range $range, string $message, $severity = null, $code = null, ?CodeDescription $codeDescription = null, ?string $source = null, ?array $tags = null, ?array $relatedInformation = null, $data = null)
     {
         $this->range = $range;
         $this->severity = $severity;
         $this->code = $code;
+        $this->codeDescription = $codeDescription;
         $this->source = $source;
         $this->message = $message;
         $this->tags = $tags;
         $this->relatedInformation = $relatedInformation;
+        $this->data = $data;
     }
 
     /**
@@ -95,10 +114,12 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'range' => ['names' => [Range::class], 'iterable' => false],
             'severity' => ['names' => [], 'iterable' => false],
             'code' => ['names' => [], 'iterable' => false],
+            'codeDescription' => ['names' => [CodeDescription::class], 'iterable' => false],
             'source' => ['names' => [], 'iterable' => false],
             'message' => ['names' => [], 'iterable' => false],
             'tags' => ['names' => [], 'iterable' => true],
             'relatedInformation' => ['names' => [DiagnosticRelatedInformation::class], 'iterable' => true],
+            'data' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/DidChangeTextDocumentParams.php b/src/DidChangeTextDocumentParams.php
index ecb53b2..18da855 100644
--- a/src/DidChangeTextDocumentParams.php
+++ b/src/DidChangeTextDocumentParams.php
@@ -29,7 +29,7 @@ class DidChangeTextDocumentParams
      * 
      * To mirror the content of a document using change events use the following approach:
      * - start with the same initial content
-     * - apply the 'textDocument/didChange' notifications in the order you recevie them.
+     * - apply the 'textDocument/didChange' notifications in the order you receive them.
      * - apply the `TextDocumentContentChangeEvent`s in a single notification in the order
      *    you receive them.
      *
diff --git a/src/DidCreateFilesNotification.php b/src/DidCreateFilesNotification.php
new file mode 100644
index 0000000..80397d2
--- /dev/null
+++ b/src/DidCreateFilesNotification.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface DidCreateFilesNotification
+{
+    public const METHOD = 'workspace/didCreateFiles';
+}
\ No newline at end of file
diff --git a/src/DidDeleteFilesNotification.php b/src/DidDeleteFilesNotification.php
new file mode 100644
index 0000000..3330990
--- /dev/null
+++ b/src/DidDeleteFilesNotification.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface DidDeleteFilesNotification
+{
+    public const METHOD = 'workspace/didDeleteFiles';
+}
\ No newline at end of file
diff --git a/src/DidRenameFilesNotification.php b/src/DidRenameFilesNotification.php
new file mode 100644
index 0000000..d01b0c5
--- /dev/null
+++ b/src/DidRenameFilesNotification.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface DidRenameFilesNotification
+{
+    public const METHOD = 'workspace/didRenameFiles';
+}
\ No newline at end of file
diff --git a/src/DidSaveTextDocumentParams.php b/src/DidSaveTextDocumentParams.php
index 9f32460..ae63141 100644
--- a/src/DidSaveTextDocumentParams.php
+++ b/src/DidSaveTextDocumentParams.php
@@ -14,7 +14,7 @@ class DidSaveTextDocumentParams
     /**
      * The document that was closed.
      *
-     * @var VersionedTextDocumentIdentifier
+     * @var TextDocumentIdentifier
      */
     public $textDocument;
 
@@ -27,10 +27,10 @@ class DidSaveTextDocumentParams
     public $text;
 
     /**
-     * @param VersionedTextDocumentIdentifier $textDocument
+     * @param TextDocumentIdentifier $textDocument
      * @param string|null $text
      */
-    public function __construct(VersionedTextDocumentIdentifier $textDocument, ?string $text = null)
+    public function __construct(TextDocumentIdentifier $textDocument, ?string $text = null)
     {
         $this->textDocument = $textDocument;
         $this->text = $text;
@@ -43,7 +43,7 @@ public function __construct(VersionedTextDocumentIdentifier $textDocument, ?stri
     public static function fromArray(array $array, bool $allowUnknownKeys = false)
     {
         $map = [
-            'textDocument' => ['names' => [VersionedTextDocumentIdentifier::class], 'iterable' => false],
+            'textDocument' => ['names' => [TextDocumentIdentifier::class], 'iterable' => false],
             'text' => ['names' => [], 'iterable' => false],
         ];
 
diff --git a/src/DocumentLinkResolveRequest.php b/src/DocumentLinkResolveRequest.php
new file mode 100644
index 0000000..b7779d6
--- /dev/null
+++ b/src/DocumentLinkResolveRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface DocumentLinkResolveRequest
+{
+    public const METHOD = 'documentLink/resolve';
+}
\ No newline at end of file
diff --git a/src/DocumentSymbol.php b/src/DocumentSymbol.php
index 433a75b..98360bb 100644
--- a/src/DocumentSymbol.php
+++ b/src/DocumentSymbol.php
@@ -36,6 +36,13 @@ class DocumentSymbol
      */
     public $kind;
 
+    /**
+     * Tags for this completion item.
+     *
+     * @var array<SymbolTag::*>|null
+     */
+    public $tags;
+
     /**
      * Indicates if this symbol is deprecated.
      *
@@ -71,16 +78,18 @@ class DocumentSymbol
      * @param string $name
      * @param string|null $detail
      * @param SymbolKind::* $kind
+     * @param array<SymbolTag::*>|null $tags
      * @param bool|null $deprecated
      * @param Range $range
      * @param Range $selectionRange
      * @param array<DocumentSymbol>|null $children
      */
-    public function __construct(string $name, $kind, Range $range, Range $selectionRange, ?string $detail = null, ?bool $deprecated = null, ?array $children = null)
+    public function __construct(string $name, $kind, Range $range, Range $selectionRange, ?string $detail = null, ?array $tags = null, ?bool $deprecated = null, ?array $children = null)
     {
         $this->name = $name;
         $this->detail = $detail;
         $this->kind = $kind;
+        $this->tags = $tags;
         $this->deprecated = $deprecated;
         $this->range = $range;
         $this->selectionRange = $selectionRange;
@@ -97,6 +106,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'name' => ['names' => [], 'iterable' => false],
             'detail' => ['names' => [], 'iterable' => false],
             'kind' => ['names' => [], 'iterable' => false],
+            'tags' => ['names' => [], 'iterable' => true],
             'deprecated' => ['names' => [], 'iterable' => false],
             'range' => ['names' => [Range::class], 'iterable' => false],
             'selectionRange' => ['names' => [Range::class], 'iterable' => false],
diff --git a/src/DocumentSymbolClientCapabilities.php b/src/DocumentSymbolClientCapabilities.php
index 20f37bc..cbabe58 100644
--- a/src/DocumentSymbolClientCapabilities.php
+++ b/src/DocumentSymbolClientCapabilities.php
@@ -32,16 +32,37 @@ class DocumentSymbolClientCapabilities
      */
     public $hierarchicalDocumentSymbolSupport;
 
+    /**
+     * The client supports tags on `SymbolInformation`. Tags are supported on
+     * `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true.
+     * Clients supporting tags have to handle unknown tags gracefully.
+     *
+     * @var array<mixed>|null
+     */
+    public $tagSupport;
+
+    /**
+     * The client supports an additional label presented in the UI when
+     * registering a document symbol provider.
+     *
+     * @var bool|null
+     */
+    public $labelSupport;
+
     /**
      * @param bool|null $dynamicRegistration
      * @param array<mixed>|null $symbolKind
      * @param bool|null $hierarchicalDocumentSymbolSupport
+     * @param array<mixed>|null $tagSupport
+     * @param bool|null $labelSupport
      */
-    public function __construct(?bool $dynamicRegistration = null, ?array $symbolKind = null, ?bool $hierarchicalDocumentSymbolSupport = null)
+    public function __construct(?bool $dynamicRegistration = null, ?array $symbolKind = null, ?bool $hierarchicalDocumentSymbolSupport = null, ?array $tagSupport = null, ?bool $labelSupport = null)
     {
         $this->dynamicRegistration = $dynamicRegistration;
         $this->symbolKind = $symbolKind;
         $this->hierarchicalDocumentSymbolSupport = $hierarchicalDocumentSymbolSupport;
+        $this->tagSupport = $tagSupport;
+        $this->labelSupport = $labelSupport;
     }
 
     /**
@@ -54,6 +75,8 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'dynamicRegistration' => ['names' => [], 'iterable' => false],
             'symbolKind' => ['names' => [], 'iterable' => false],
             'hierarchicalDocumentSymbolSupport' => ['names' => [], 'iterable' => false],
+            'tagSupport' => ['names' => [], 'iterable' => false],
+            'labelSupport' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/DocumentSymbolOptions.php b/src/DocumentSymbolOptions.php
index b47c099..ef959dc 100644
--- a/src/DocumentSymbolOptions.php
+++ b/src/DocumentSymbolOptions.php
@@ -13,6 +13,14 @@
  */
 class DocumentSymbolOptions extends WorkDoneProgressOptions
 {
+    /**
+     * A human-readable string that is shown when multiple outlines trees
+     * are shown for the same document.
+     *
+     * @var string|null
+     */
+    public $label;
+
     /**
      *
      * @var bool|null
@@ -20,10 +28,12 @@ class DocumentSymbolOptions extends WorkDoneProgressOptions
     public $workDoneProgress;
 
     /**
+     * @param string|null $label
      * @param bool|null $workDoneProgress
      */
-    public function __construct(?bool $workDoneProgress = null)
+    public function __construct(?string $label = null, ?bool $workDoneProgress = null)
     {
+        $this->label = $label;
         $this->workDoneProgress = $workDoneProgress;
     }
 
@@ -34,6 +44,7 @@ public function __construct(?bool $workDoneProgress = null)
     public static function fromArray(array $array, bool $allowUnknownKeys = false)
     {
         $map = [
+            'label' => ['names' => [], 'iterable' => false],
             'workDoneProgress' => ['names' => [], 'iterable' => false],
         ];
 
diff --git a/src/DocumentSymbolRegistrationOptions.php b/src/DocumentSymbolRegistrationOptions.php
index 7d830cd..10161bb 100644
--- a/src/DocumentSymbolRegistrationOptions.php
+++ b/src/DocumentSymbolRegistrationOptions.php
@@ -21,6 +21,14 @@ class DocumentSymbolRegistrationOptions extends TextDocumentRegistrationOptions
      */
     public $documentSelector;
 
+    /**
+     * A human-readable string that is shown when multiple outlines trees
+     * are shown for the same document.
+     *
+     * @var string|null
+     */
+    public $label;
+
     /**
      *
      * @var bool|null
@@ -29,11 +37,13 @@ class DocumentSymbolRegistrationOptions extends TextDocumentRegistrationOptions
 
     /**
      * @param array<(string|array<mixed>|array<mixed>|array<mixed>)>|null $documentSelector
+     * @param string|null $label
      * @param bool|null $workDoneProgress
      */
-    public function __construct($documentSelector = null, ?bool $workDoneProgress = null)
+    public function __construct($documentSelector = null, ?string $label = null, ?bool $workDoneProgress = null)
     {
         $this->documentSelector = $documentSelector;
+        $this->label = $label;
         $this->workDoneProgress = $workDoneProgress;
     }
 
@@ -45,6 +55,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
     {
         $map = [
             'documentSelector' => ['names' => [], 'iterable' => false],
+            'label' => ['names' => [], 'iterable' => false],
             'workDoneProgress' => ['names' => [], 'iterable' => false],
         ];
 
diff --git a/src/FileCreate.php b/src/FileCreate.php
new file mode 100644
index 0000000..b4ef0f8
--- /dev/null
+++ b/src/FileCreate.php
@@ -0,0 +1,102 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Represents information on a file/folder create.
+ */
+class FileCreate
+{
+    /**
+     * A file:// URI for the location of the file/folder being created.
+     *
+     * @var string
+     */
+    public $uri;
+
+    /**
+     * @param string $uri
+     */
+    public function __construct(string $uri)
+    {
+        $this->uri = $uri;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'uri' => ['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<string> $classNames
+     * @param array<string,mixed> $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/FileDelete.php b/src/FileDelete.php
new file mode 100644
index 0000000..ef775ae
--- /dev/null
+++ b/src/FileDelete.php
@@ -0,0 +1,102 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Represents information on a file/folder delete.
+ */
+class FileDelete
+{
+    /**
+     * A file:// URI for the location of the file/folder being deleted.
+     *
+     * @var string
+     */
+    public $uri;
+
+    /**
+     * @param string $uri
+     */
+    public function __construct(string $uri)
+    {
+        $this->uri = $uri;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'uri' => ['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<string> $classNames
+     * @param array<string,mixed> $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/FileOperationClientCapabilities.php b/src/FileOperationClientCapabilities.php
new file mode 100644
index 0000000..4cf7317
--- /dev/null
+++ b/src/FileOperationClientCapabilities.php
@@ -0,0 +1,165 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Capabilities relating to events from file operations by the user in the client.
+ * 
+ * These events do not come from the file system, they come from user operations
+ * like renaming a file in the UI.
+ */
+class FileOperationClientCapabilities
+{
+    /**
+     * Whether the client supports dynamic registration for file requests/notifications.
+     *
+     * @var bool|null
+     */
+    public $dynamicRegistration;
+
+    /**
+     * The client has support for sending didCreateFiles notifications.
+     *
+     * @var bool|null
+     */
+    public $didCreate;
+
+    /**
+     * The client has support for willCreateFiles requests.
+     *
+     * @var bool|null
+     */
+    public $willCreate;
+
+    /**
+     * The client has support for sending didRenameFiles notifications.
+     *
+     * @var bool|null
+     */
+    public $didRename;
+
+    /**
+     * The client has support for willRenameFiles requests.
+     *
+     * @var bool|null
+     */
+    public $willRename;
+
+    /**
+     * The client has support for sending didDeleteFiles notifications.
+     *
+     * @var bool|null
+     */
+    public $didDelete;
+
+    /**
+     * The client has support for willDeleteFiles requests.
+     *
+     * @var bool|null
+     */
+    public $willDelete;
+
+    /**
+     * @param bool|null $dynamicRegistration
+     * @param bool|null $didCreate
+     * @param bool|null $willCreate
+     * @param bool|null $didRename
+     * @param bool|null $willRename
+     * @param bool|null $didDelete
+     * @param bool|null $willDelete
+     */
+    public function __construct(?bool $dynamicRegistration = null, ?bool $didCreate = null, ?bool $willCreate = null, ?bool $didRename = null, ?bool $willRename = null, ?bool $didDelete = null, ?bool $willDelete = null)
+    {
+        $this->dynamicRegistration = $dynamicRegistration;
+        $this->didCreate = $didCreate;
+        $this->willCreate = $willCreate;
+        $this->didRename = $didRename;
+        $this->willRename = $willRename;
+        $this->didDelete = $didDelete;
+        $this->willDelete = $willDelete;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'dynamicRegistration' => ['names' => [], 'iterable' => false],
+            'didCreate' => ['names' => [], 'iterable' => false],
+            'willCreate' => ['names' => [], 'iterable' => false],
+            'didRename' => ['names' => [], 'iterable' => false],
+            'willRename' => ['names' => [], 'iterable' => false],
+            'didDelete' => ['names' => [], 'iterable' => false],
+            'willDelete' => ['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<string> $classNames
+     * @param array<string,mixed> $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/FileOperationFilter.php b/src/FileOperationFilter.php
new file mode 100644
index 0000000..7323b79
--- /dev/null
+++ b/src/FileOperationFilter.php
@@ -0,0 +1,113 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * A filter to describe in which file operation requests or notifications
+ * the server is interested in.
+ */
+class FileOperationFilter
+{
+    /**
+     * A Uri like `file` or `untitled`.
+     *
+     * @var string|null
+     */
+    public $scheme;
+
+    /**
+     * The actual file operation pattern.
+     *
+     * @var FileOperationPattern
+     */
+    public $pattern;
+
+    /**
+     * @param string|null $scheme
+     * @param FileOperationPattern $pattern
+     */
+    public function __construct(FileOperationPattern $pattern, ?string $scheme = null)
+    {
+        $this->scheme = $scheme;
+        $this->pattern = $pattern;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'scheme' => ['names' => [], 'iterable' => false],
+            'pattern' => ['names' => [FileOperationPattern::class], '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<string> $classNames
+     * @param array<string,mixed> $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/FileOperationOptions.php b/src/FileOperationOptions.php
new file mode 100644
index 0000000..04e5db6
--- /dev/null
+++ b/src/FileOperationOptions.php
@@ -0,0 +1,152 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Options for notifications/requests for user operations on files.
+ */
+class FileOperationOptions
+{
+    /**
+     * The server is interested in didCreateFiles notifications.
+     *
+     * @var FileOperationRegistrationOptions|null
+     */
+    public $didCreate;
+
+    /**
+     * The server is interested in willCreateFiles requests.
+     *
+     * @var FileOperationRegistrationOptions|null
+     */
+    public $willCreate;
+
+    /**
+     * The server is interested in didRenameFiles notifications.
+     *
+     * @var FileOperationRegistrationOptions|null
+     */
+    public $didRename;
+
+    /**
+     * The server is interested in willRenameFiles requests.
+     *
+     * @var FileOperationRegistrationOptions|null
+     */
+    public $willRename;
+
+    /**
+     * The server is interested in didDeleteFiles file notifications.
+     *
+     * @var FileOperationRegistrationOptions|null
+     */
+    public $didDelete;
+
+    /**
+     * The server is interested in willDeleteFiles file requests.
+     *
+     * @var FileOperationRegistrationOptions|null
+     */
+    public $willDelete;
+
+    /**
+     * @param FileOperationRegistrationOptions|null $didCreate
+     * @param FileOperationRegistrationOptions|null $willCreate
+     * @param FileOperationRegistrationOptions|null $didRename
+     * @param FileOperationRegistrationOptions|null $willRename
+     * @param FileOperationRegistrationOptions|null $didDelete
+     * @param FileOperationRegistrationOptions|null $willDelete
+     */
+    public function __construct(?FileOperationRegistrationOptions $didCreate = null, ?FileOperationRegistrationOptions $willCreate = null, ?FileOperationRegistrationOptions $didRename = null, ?FileOperationRegistrationOptions $willRename = null, ?FileOperationRegistrationOptions $didDelete = null, ?FileOperationRegistrationOptions $willDelete = null)
+    {
+        $this->didCreate = $didCreate;
+        $this->willCreate = $willCreate;
+        $this->didRename = $didRename;
+        $this->willRename = $willRename;
+        $this->didDelete = $didDelete;
+        $this->willDelete = $willDelete;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'didCreate' => ['names' => [FileOperationRegistrationOptions::class], 'iterable' => false],
+            'willCreate' => ['names' => [FileOperationRegistrationOptions::class], 'iterable' => false],
+            'didRename' => ['names' => [FileOperationRegistrationOptions::class], 'iterable' => false],
+            'willRename' => ['names' => [FileOperationRegistrationOptions::class], 'iterable' => false],
+            'didDelete' => ['names' => [FileOperationRegistrationOptions::class], 'iterable' => false],
+            'willDelete' => ['names' => [FileOperationRegistrationOptions::class], '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<string> $classNames
+     * @param array<string,mixed> $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/FileOperationPattern.php b/src/FileOperationPattern.php
new file mode 100644
index 0000000..337a001
--- /dev/null
+++ b/src/FileOperationPattern.php
@@ -0,0 +1,131 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * A pattern to describe in which file operation requests or notifications
+ * the server is interested in.
+ */
+class FileOperationPattern
+{
+    /**
+     * The glob pattern to match. Glob patterns can have the following syntax:
+     * - `*` to match one or more characters in a path segment
+     * - `?` to match on one character in a path segment
+     * - `**` to match any number of path segments, including none
+     * - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)
+     * - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
+     * - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
+     *
+     * @var string
+     */
+    public $glob;
+
+    /**
+     * Whether to match files or folders with this pattern.
+     * 
+     * Matches both if undefined.
+     *
+     * @var FileOperationPatternKind::*|null
+     */
+    public $matches;
+
+    /**
+     * Additional options used during matching.
+     *
+     * @var FileOperationPatternOptions|null
+     */
+    public $options;
+
+    /**
+     * @param string $glob
+     * @param FileOperationPatternKind::*|null $matches
+     * @param FileOperationPatternOptions|null $options
+     */
+    public function __construct(string $glob, $matches = null, ?FileOperationPatternOptions $options = null)
+    {
+        $this->glob = $glob;
+        $this->matches = $matches;
+        $this->options = $options;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'glob' => ['names' => [], 'iterable' => false],
+            'matches' => ['names' => [], 'iterable' => false],
+            'options' => ['names' => [FileOperationPatternOptions::class], '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<string> $classNames
+     * @param array<string,mixed> $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/FileOperationPatternKind.php b/src/FileOperationPatternKind.php
new file mode 100644
index 0000000..78cca2a
--- /dev/null
+++ b/src/FileOperationPatternKind.php
@@ -0,0 +1,9 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface FileOperationPatternKind
+{
+    public const FILE = 'file';
+    public const FOLDER = 'folder';
+}
\ No newline at end of file
diff --git a/src/FileOperationPatternOptions.php b/src/FileOperationPatternOptions.php
new file mode 100644
index 0000000..bb4f3b5
--- /dev/null
+++ b/src/FileOperationPatternOptions.php
@@ -0,0 +1,102 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Matching options for the file operation pattern.
+ */
+class FileOperationPatternOptions
+{
+    /**
+     * The pattern should be matched ignoring casing.
+     *
+     * @var bool|null
+     */
+    public $ignoreCase;
+
+    /**
+     * @param bool|null $ignoreCase
+     */
+    public function __construct(?bool $ignoreCase = null)
+    {
+        $this->ignoreCase = $ignoreCase;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'ignoreCase' => ['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<string> $classNames
+     * @param array<string,mixed> $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/FileOperationRegistrationOptions.php b/src/FileOperationRegistrationOptions.php
new file mode 100644
index 0000000..606e843
--- /dev/null
+++ b/src/FileOperationRegistrationOptions.php
@@ -0,0 +1,102 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * The options to register for file operations.
+ */
+class FileOperationRegistrationOptions
+{
+    /**
+     * The actual filters.
+     *
+     * @var array<FileOperationFilter>
+     */
+    public $filters;
+
+    /**
+     * @param array<FileOperationFilter> $filters
+     */
+    public function __construct(array $filters)
+    {
+        $this->filters = $filters;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'filters' => ['names' => [FileOperationFilter::class], 'iterable' => true],
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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/FileRename.php b/src/FileRename.php
new file mode 100644
index 0000000..9fdc8a9
--- /dev/null
+++ b/src/FileRename.php
@@ -0,0 +1,112 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Represents information on a file/folder rename.
+ */
+class FileRename
+{
+    /**
+     * A file:// URI for the original location of the file/folder being renamed.
+     *
+     * @var string
+     */
+    public $oldUri;
+
+    /**
+     * A file:// URI for the new location of the file/folder being renamed.
+     *
+     * @var string
+     */
+    public $newUri;
+
+    /**
+     * @param string $oldUri
+     * @param string $newUri
+     */
+    public function __construct(string $oldUri, string $newUri)
+    {
+        $this->oldUri = $oldUri;
+        $this->newUri = $newUri;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'oldUri' => ['names' => [], 'iterable' => false],
+            'newUri' => ['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<string> $classNames
+     * @param array<string,mixed> $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/FoldingRange.php b/src/FoldingRange.php
index 4850837..240aba7 100644
--- a/src/FoldingRange.php
+++ b/src/FoldingRange.php
@@ -7,12 +7,14 @@
 use RuntimeException;
 
 /**
- * Represents a folding range.
+ * Represents a folding range. To be valid, start and end line must be bigger than zero and smaller
+ * than the number of lines in the document. Clients are free to ignore invalid ranges.
  */
 class FoldingRange
 {
     /**
-     * The zero-based line number from where the folded range starts.
+     * The zero-based start line of the range to fold. The folded area starts after the line's last character.
+     * To be valid, the end must be zero or larger and smaller than the number of lines in the document.
      *
      * @var int
      */
@@ -26,7 +28,8 @@ class FoldingRange
     public $startCharacter;
 
     /**
-     * The zero-based line number where the folded range ends.
+     * The zero-based end line of the range to fold. The folded area ends with the line's last character.
+     * To be valid, the end must be zero or larger and smaller than the number of lines in the document.
      *
      * @var int
      */
diff --git a/src/GeneralClientCapabilities.php b/src/GeneralClientCapabilities.php
new file mode 100644
index 0000000..711ebd2
--- /dev/null
+++ b/src/GeneralClientCapabilities.php
@@ -0,0 +1,112 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * General client capabilities.
+ */
+class GeneralClientCapabilities
+{
+    /**
+     * Client capabilities specific to regular expressions.
+     *
+     * @var RegularExpressionsClientCapabilities|null
+     */
+    public $regularExpressions;
+
+    /**
+     * Client capabilities specific to the client's markdown parser.
+     *
+     * @var MarkdownClientCapabilities|null
+     */
+    public $markdown;
+
+    /**
+     * @param RegularExpressionsClientCapabilities|null $regularExpressions
+     * @param MarkdownClientCapabilities|null $markdown
+     */
+    public function __construct(?RegularExpressionsClientCapabilities $regularExpressions = null, ?MarkdownClientCapabilities $markdown = null)
+    {
+        $this->regularExpressions = $regularExpressions;
+        $this->markdown = $markdown;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'regularExpressions' => ['names' => [RegularExpressionsClientCapabilities::class], 'iterable' => false],
+            'markdown' => ['names' => [MarkdownClientCapabilities::class], '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<string> $classNames
+     * @param array<string,mixed> $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/ImplementationClientCapabilities.php b/src/ImplementationClientCapabilities.php
index f363aa5..21842a4 100644
--- a/src/ImplementationClientCapabilities.php
+++ b/src/ImplementationClientCapabilities.php
@@ -7,7 +7,6 @@
 use RuntimeException;
 
 /**
- * Since 3.6.0
  */
 class ImplementationClientCapabilities
 {
@@ -22,8 +21,6 @@ class ImplementationClientCapabilities
 
     /**
      * The client supports additional metadata in the form of definition links.
-     * 
-     * Since 3.14.0
      *
      * @var bool|null
      */
diff --git a/src/InitializeParams.php b/src/InitializeParams.php
index 548cbc4..d07a493 100644
--- a/src/InitializeParams.php
+++ b/src/InitializeParams.php
@@ -15,7 +15,7 @@ class InitializeParams
      * The process Id of the parent process that started
      * the server.
      *
-     * @var int|null
+     * @var integer::*|null
      */
     public $processId;
 
@@ -26,6 +26,18 @@ class InitializeParams
      */
     public $clientInfo;
 
+    /**
+     * The locale the client is currently showing the user interface
+     * in. This must not necessarily be the locale of the operating
+     * system.
+     * 
+     * Uses IETF language tags as the value's syntax
+     * (See https://en.wikipedia.org/wiki/IETF_language_tag)
+     *
+     * @var string|null
+     */
+    public $locale;
+
     /**
      * The rootPath of the workspace. Is null
      * if no folder is open.
@@ -79,8 +91,9 @@ class InitializeParams
     public $workspaceFolders;
 
     /**
-     * @param int|null $processId
+     * @param integer::*|null $processId
      * @param array<mixed>|null $clientInfo
+     * @param string|null $locale
      * @param string|null $rootPath
      * @param string|null $rootUri
      * @param ClientCapabilities $capabilities
@@ -89,10 +102,11 @@ class InitializeParams
      * @param int|string|null $workDoneToken
      * @param array<WorkspaceFolder>|null $workspaceFolders
      */
-    public function __construct(ClientCapabilities $capabilities, $processId = null, ?array $clientInfo = null, $rootPath = null, $rootUri = null, $initializationOptions = null, $trace = null, $workDoneToken = null, $workspaceFolders = null)
+    public function __construct(ClientCapabilities $capabilities, $processId = null, ?array $clientInfo = null, ?string $locale = null, $rootPath = null, $rootUri = null, $initializationOptions = null, $trace = null, $workDoneToken = null, $workspaceFolders = null)
     {
         $this->processId = $processId;
         $this->clientInfo = $clientInfo;
+        $this->locale = $locale;
         $this->rootPath = $rootPath;
         $this->rootUri = $rootUri;
         $this->capabilities = $capabilities;
@@ -111,6 +125,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
         $map = [
             'processId' => ['names' => [], 'iterable' => false],
             'clientInfo' => ['names' => [], 'iterable' => false],
+            'locale' => ['names' => [], 'iterable' => false],
             'rootPath' => ['names' => [], 'iterable' => false],
             'rootUri' => ['names' => [], 'iterable' => false],
             'capabilities' => ['names' => [ClientCapabilities::class], 'iterable' => false],
diff --git a/src/InsertReplaceEdit.php b/src/InsertReplaceEdit.php
new file mode 100644
index 0000000..0e2f523
--- /dev/null
+++ b/src/InsertReplaceEdit.php
@@ -0,0 +1,122 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * A special text edit to provide an insert and a replace operation.
+ */
+class InsertReplaceEdit
+{
+    /**
+     * The string to be inserted.
+     *
+     * @var string
+     */
+    public $newText;
+
+    /**
+     * The range if the insert is requested
+     *
+     * @var Range
+     */
+    public $insert;
+
+    /**
+     * The range if the replace is requested.
+     *
+     * @var Range
+     */
+    public $replace;
+
+    /**
+     * @param string $newText
+     * @param Range $insert
+     * @param Range $replace
+     */
+    public function __construct(string $newText, Range $insert, Range $replace)
+    {
+        $this->newText = $newText;
+        $this->insert = $insert;
+        $this->replace = $replace;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'newText' => ['names' => [], 'iterable' => false],
+            'insert' => ['names' => [Range::class], 'iterable' => false],
+            'replace' => ['names' => [Range::class], '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<string> $classNames
+     * @param array<string,mixed> $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/InsertTextMode.php b/src/InsertTextMode.php
new file mode 100644
index 0000000..ee72ab7
--- /dev/null
+++ b/src/InsertTextMode.php
@@ -0,0 +1,9 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface InsertTextMode
+{
+    public const AS_IS = 1;
+    public const ADJUST_INDENTATION = 2;
+}
\ No newline at end of file
diff --git a/src/LinkedEditingRangeClientCapabilities.php b/src/LinkedEditingRangeClientCapabilities.php
new file mode 100644
index 0000000..ac28a90
--- /dev/null
+++ b/src/LinkedEditingRangeClientCapabilities.php
@@ -0,0 +1,104 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Client capabilities for the linked editing range request.
+ */
+class LinkedEditingRangeClientCapabilities
+{
+    /**
+     * Whether implementation supports dynamic registration. If this is set to `true`
+     * the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
+     * return value for the corresponding server capability as well.
+     *
+     * @var bool|null
+     */
+    public $dynamicRegistration;
+
+    /**
+     * @param bool|null $dynamicRegistration
+     */
+    public function __construct(?bool $dynamicRegistration = null)
+    {
+        $this->dynamicRegistration = $dynamicRegistration;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    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<string> $classNames
+     * @param array<string,mixed> $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/LinkedEditingRangeOptions.php b/src/LinkedEditingRangeOptions.php
new file mode 100644
index 0000000..e9b5232
--- /dev/null
+++ b/src/LinkedEditingRangeOptions.php
@@ -0,0 +1,101 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Mixins (implemented TS interfaces): WorkDoneProgressOptions
+ */
+class LinkedEditingRangeOptions extends WorkDoneProgressOptions
+{
+    /**
+     *
+     * @var bool|null
+     */
+    public $workDoneProgress;
+
+    /**
+     * @param bool|null $workDoneProgress
+     */
+    public function __construct(?bool $workDoneProgress = null)
+    {
+        $this->workDoneProgress = $workDoneProgress;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    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<string> $classNames
+     * @param array<string,mixed> $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/LinkedEditingRangeParams.php b/src/LinkedEditingRangeParams.php
new file mode 100644
index 0000000..34652e0
--- /dev/null
+++ b/src/LinkedEditingRangeParams.php
@@ -0,0 +1,122 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Mixins (implemented TS interfaces): TextDocumentPositionParams, WorkDoneProgressParams
+ */
+class LinkedEditingRangeParams extends TextDocumentPositionParams
+{
+    /**
+     * The text document.
+     *
+     * @var TextDocumentIdentifier
+     */
+    public $textDocument;
+
+    /**
+     * The position inside the text document.
+     *
+     * @var Position
+     */
+    public $position;
+
+    /**
+     * An optional token that a server can use to report work done progress.
+     *
+     * @var int|string|null
+     */
+    public $workDoneToken;
+
+    /**
+     * @param TextDocumentIdentifier $textDocument
+     * @param Position $position
+     * @param int|string|null $workDoneToken
+     */
+    public function __construct(TextDocumentIdentifier $textDocument, Position $position, $workDoneToken = null)
+    {
+        $this->textDocument = $textDocument;
+        $this->position = $position;
+        $this->workDoneToken = $workDoneToken;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    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<string> $classNames
+     * @param array<string,mixed> $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/LinkedEditingRangeRegistrationOptions.php b/src/LinkedEditingRangeRegistrationOptions.php
new file mode 100644
index 0000000..0fbf035
--- /dev/null
+++ b/src/LinkedEditingRangeRegistrationOptions.php
@@ -0,0 +1,123 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Mixins (implemented TS interfaces): TextDocumentRegistrationOptions, LinkedEditingRangeOptions, StaticRegistrationOptions
+ */
+class LinkedEditingRangeRegistrationOptions extends TextDocumentRegistrationOptions
+{
+    /**
+     * A document selector to identify the scope of the registration. If set to null
+     * the document selector provided on the client side will be used.
+     *
+     * @var array<(string|array<mixed>|array<mixed>|array<mixed>)>|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<mixed>|array<mixed>|array<mixed>)>|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<string,mixed> $array
+     * @return static
+     */
+    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<string> $classNames
+     * @param array<string,mixed> $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/LinkedEditingRangeRequest.php b/src/LinkedEditingRangeRequest.php
new file mode 100644
index 0000000..b171306
--- /dev/null
+++ b/src/LinkedEditingRangeRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface LinkedEditingRangeRequest
+{
+    public const METHOD = 'textDocument/linkedEditingRange';
+}
\ No newline at end of file
diff --git a/src/LinkedEditingRanges.php b/src/LinkedEditingRanges.php
new file mode 100644
index 0000000..c04a4e6
--- /dev/null
+++ b/src/LinkedEditingRanges.php
@@ -0,0 +1,115 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * The result of a linked editing range request.
+ */
+class LinkedEditingRanges
+{
+    /**
+     * A list of ranges that can be edited together. The ranges must have
+     * identical length and contain identical text content. The ranges cannot overlap.
+     *
+     * @var array<Range>
+     */
+    public $ranges;
+
+    /**
+     * An optional word pattern (regular expression) that describes valid contents for
+     * the given ranges. If no pattern is provided, the client configuration's word
+     * pattern will be used.
+     *
+     * @var string|null
+     */
+    public $wordPattern;
+
+    /**
+     * @param array<Range> $ranges
+     * @param string|null $wordPattern
+     */
+    public function __construct(array $ranges, ?string $wordPattern = null)
+    {
+        $this->ranges = $ranges;
+        $this->wordPattern = $wordPattern;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'ranges' => ['names' => [Range::class], 'iterable' => true],
+            'wordPattern' => ['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<string> $classNames
+     * @param array<string,mixed> $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/MarkdownClientCapabilities.php b/src/MarkdownClientCapabilities.php
new file mode 100644
index 0000000..31905a7
--- /dev/null
+++ b/src/MarkdownClientCapabilities.php
@@ -0,0 +1,112 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Client capabilities specific to the used markdown parser.
+ */
+class MarkdownClientCapabilities
+{
+    /**
+     * The name of the parser.
+     *
+     * @var string
+     */
+    public $parser;
+
+    /**
+     * The version of the parser.
+     *
+     * @var string|null
+     */
+    public $version;
+
+    /**
+     * @param string $parser
+     * @param string|null $version
+     */
+    public function __construct(string $parser, ?string $version = null)
+    {
+        $this->parser = $parser;
+        $this->version = $version;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'parser' => ['names' => [], 'iterable' => false],
+            'version' => ['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<string> $classNames
+     * @param array<string,mixed> $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/Moniker.php b/src/Moniker.php
new file mode 100644
index 0000000..7e3a772
--- /dev/null
+++ b/src/Moniker.php
@@ -0,0 +1,133 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Moniker definition to match LSIF 0.5 moniker definition.
+ */
+class Moniker
+{
+    /**
+     * The scheme of the moniker. For example tsc or .Net
+     *
+     * @var string
+     */
+    public $scheme;
+
+    /**
+     * The identifier of the moniker. The value is opaque in LSIF however
+     * schema owners are allowed to define the structure if they want.
+     *
+     * @var string
+     */
+    public $identifier;
+
+    /**
+     * The scope in which the moniker is unique
+     *
+     * @var mixed
+     */
+    public $unique;
+
+    /**
+     * The moniker kind if known.
+     *
+     * @var mixed|null
+     */
+    public $kind;
+
+    /**
+     * @param string $scheme
+     * @param string $identifier
+     * @param mixed $unique
+     * @param mixed|null $kind
+     */
+    public function __construct(string $scheme, string $identifier, $unique, $kind = null)
+    {
+        $this->scheme = $scheme;
+        $this->identifier = $identifier;
+        $this->unique = $unique;
+        $this->kind = $kind;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'scheme' => ['names' => [], 'iterable' => false],
+            'identifier' => ['names' => [], 'iterable' => false],
+            'unique' => ['names' => [], 'iterable' => false],
+            'kind' => ['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<string> $classNames
+     * @param array<string,mixed> $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/MonikerClientCapabilities.php b/src/MonikerClientCapabilities.php
new file mode 100644
index 0000000..ba91a0e
--- /dev/null
+++ b/src/MonikerClientCapabilities.php
@@ -0,0 +1,104 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Client capabilities specific to the moniker request.
+ */
+class MonikerClientCapabilities
+{
+    /**
+     * Whether moniker supports dynamic registration. If this is set to `true`
+     * the client supports the new `MonikerRegistrationOptions` return value
+     * for the corresponding server capability as well.
+     *
+     * @var bool|null
+     */
+    public $dynamicRegistration;
+
+    /**
+     * @param bool|null $dynamicRegistration
+     */
+    public function __construct(?bool $dynamicRegistration = null)
+    {
+        $this->dynamicRegistration = $dynamicRegistration;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    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<string> $classNames
+     * @param array<string,mixed> $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/MonikerOptions.php b/src/MonikerOptions.php
new file mode 100644
index 0000000..8fec9cf
--- /dev/null
+++ b/src/MonikerOptions.php
@@ -0,0 +1,101 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Mixins (implemented TS interfaces): WorkDoneProgressOptions
+ */
+class MonikerOptions extends WorkDoneProgressOptions
+{
+    /**
+     *
+     * @var bool|null
+     */
+    public $workDoneProgress;
+
+    /**
+     * @param bool|null $workDoneProgress
+     */
+    public function __construct(?bool $workDoneProgress = null)
+    {
+        $this->workDoneProgress = $workDoneProgress;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    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<string> $classNames
+     * @param array<string,mixed> $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/MonikerParams.php b/src/MonikerParams.php
new file mode 100644
index 0000000..1351951
--- /dev/null
+++ b/src/MonikerParams.php
@@ -0,0 +1,133 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Mixins (implemented TS interfaces): TextDocumentPositionParams, WorkDoneProgressParams, PartialResultParams
+ */
+class MonikerParams extends TextDocumentPositionParams
+{
+    /**
+     * The text document.
+     *
+     * @var TextDocumentIdentifier
+     */
+    public $textDocument;
+
+    /**
+     * The position inside the text document.
+     *
+     * @var Position
+     */
+    public $position;
+
+    /**
+     * An optional token that a server can use to report work done progress.
+     *
+     * @var int|string|null
+     */
+    public $workDoneToken;
+
+    /**
+     * An optional token that a server can use to report partial results (e.g. streaming) to
+     * the client.
+     *
+     * @var int|string|null
+     */
+    public $partialResultToken;
+
+    /**
+     * @param TextDocumentIdentifier $textDocument
+     * @param Position $position
+     * @param int|string|null $workDoneToken
+     * @param int|string|null $partialResultToken
+     */
+    public function __construct(TextDocumentIdentifier $textDocument, Position $position, $workDoneToken = null, $partialResultToken = null)
+    {
+        $this->textDocument = $textDocument;
+        $this->position = $position;
+        $this->workDoneToken = $workDoneToken;
+        $this->partialResultToken = $partialResultToken;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    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],
+            '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<string> $classNames
+     * @param array<string,mixed> $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/MonikerRegistrationOptions.php b/src/MonikerRegistrationOptions.php
new file mode 100644
index 0000000..9c85192
--- /dev/null
+++ b/src/MonikerRegistrationOptions.php
@@ -0,0 +1,112 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Mixins (implemented TS interfaces): TextDocumentRegistrationOptions, MonikerOptions
+ */
+class MonikerRegistrationOptions extends TextDocumentRegistrationOptions
+{
+    /**
+     * A document selector to identify the scope of the registration. If set to null
+     * the document selector provided on the client side will be used.
+     *
+     * @var array<(string|array<mixed>|array<mixed>|array<mixed>)>|null
+     */
+    public $documentSelector;
+
+    /**
+     *
+     * @var bool|null
+     */
+    public $workDoneProgress;
+
+    /**
+     * @param array<(string|array<mixed>|array<mixed>|array<mixed>)>|null $documentSelector
+     * @param bool|null $workDoneProgress
+     */
+    public function __construct($documentSelector = null, ?bool $workDoneProgress = null)
+    {
+        $this->documentSelector = $documentSelector;
+        $this->workDoneProgress = $workDoneProgress;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'documentSelector' => ['names' => [], 'iterable' => false],
+            '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<string> $classNames
+     * @param array<string,mixed> $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/MonikerRequest.php b/src/MonikerRequest.php
new file mode 100644
index 0000000..dca7e77
--- /dev/null
+++ b/src/MonikerRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface MonikerRequest
+{
+    public const METHOD = 'textDocument/moniker';
+}
\ No newline at end of file
diff --git a/src/MonikerServerCapabilities.php b/src/MonikerServerCapabilities.php
new file mode 100644
index 0000000..acf056e
--- /dev/null
+++ b/src/MonikerServerCapabilities.php
@@ -0,0 +1,84 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+class MonikerServerCapabilities
+{
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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/OptionalVersionedTextDocumentIdentifier.php b/src/OptionalVersionedTextDocumentIdentifier.php
new file mode 100644
index 0000000..f60211b
--- /dev/null
+++ b/src/OptionalVersionedTextDocumentIdentifier.php
@@ -0,0 +1,118 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * A text document identifier to optionally denote a specific version of a text document.
+ *
+ * Mixins (implemented TS interfaces): TextDocumentIdentifier
+ */
+class OptionalVersionedTextDocumentIdentifier extends TextDocumentIdentifier
+{
+    /**
+     * The version number of this document. If a versioned text document identifier
+     * is sent from the server to the client and the file is not open in the editor
+     * (the server has not received an open notification before) the server can send
+     * `null` to indicate that the version is unknown and the content on disk is the
+     * truth (as specified with document content ownership).
+     *
+     * @var integer::*|null
+     */
+    public $version;
+
+    /**
+     * The text document's uri.
+     *
+     * @var string
+     */
+    public $uri;
+
+    /**
+     * @param integer::*|null $version
+     * @param string $uri
+     */
+    public function __construct(string $uri, $version = null)
+    {
+        $this->version = $version;
+        $this->uri = $uri;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'version' => ['names' => [], 'iterable' => false],
+            'uri' => ['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<string> $classNames
+     * @param array<string,mixed> $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/Position.php b/src/Position.php
index 01923c9..71d7a96 100644
--- a/src/Position.php
+++ b/src/Position.php
@@ -20,8 +20,6 @@ class Position
 {
     /**
      * Line position in a document (zero-based).
-     * If a line number is greater than the number of lines in a document, it defaults back to the number of lines in the document.
-     * If a line number is negative, it defaults to 0.
      *
      * @var int
      */
@@ -34,7 +32,6 @@ class Position
      * 
      * If the character value is greater than the line length it defaults back to the
      * line length.
-     * If a line number is negative, it defaults to 0.
      *
      * @var int
      */
diff --git a/src/PrepareSupportDefaultBehavior.php b/src/PrepareSupportDefaultBehavior.php
new file mode 100644
index 0000000..6dbc928
--- /dev/null
+++ b/src/PrepareSupportDefaultBehavior.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface PrepareSupportDefaultBehavior
+{
+    public const IDENTIFIER = 1;
+}
\ No newline at end of file
diff --git a/src/PublishDiagnosticsClientCapabilities.php b/src/PublishDiagnosticsClientCapabilities.php
index 0cfe5f8..454c175 100644
--- a/src/PublishDiagnosticsClientCapabilities.php
+++ b/src/PublishDiagnosticsClientCapabilities.php
@@ -34,16 +34,36 @@ class PublishDiagnosticsClientCapabilities
      */
     public $versionSupport;
 
+    /**
+     * Client supports a codeDescription property
+     *
+     * @var bool|null
+     */
+    public $codeDescriptionSupport;
+
+    /**
+     * Whether code action supports the `data` property which is
+     * preserved between a `textDocument/publishDiagnostics` and
+     * `textDocument/codeAction` request.
+     *
+     * @var bool|null
+     */
+    public $dataSupport;
+
     /**
      * @param bool|null $relatedInformation
      * @param array<mixed>|null $tagSupport
      * @param bool|null $versionSupport
+     * @param bool|null $codeDescriptionSupport
+     * @param bool|null $dataSupport
      */
-    public function __construct(?bool $relatedInformation = null, ?array $tagSupport = null, ?bool $versionSupport = null)
+    public function __construct(?bool $relatedInformation = null, ?array $tagSupport = null, ?bool $versionSupport = null, ?bool $codeDescriptionSupport = null, ?bool $dataSupport = null)
     {
         $this->relatedInformation = $relatedInformation;
         $this->tagSupport = $tagSupport;
         $this->versionSupport = $versionSupport;
+        $this->codeDescriptionSupport = $codeDescriptionSupport;
+        $this->dataSupport = $dataSupport;
     }
 
     /**
@@ -56,6 +76,8 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'relatedInformation' => ['names' => [], 'iterable' => false],
             'tagSupport' => ['names' => [], 'iterable' => false],
             'versionSupport' => ['names' => [], 'iterable' => false],
+            'codeDescriptionSupport' => ['names' => [], 'iterable' => false],
+            'dataSupport' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/PublishDiagnosticsParams.php b/src/PublishDiagnosticsParams.php
index 34d6719..e534ab5 100644
--- a/src/PublishDiagnosticsParams.php
+++ b/src/PublishDiagnosticsParams.php
@@ -21,7 +21,7 @@ class PublishDiagnosticsParams
     /**
      * Optional the version number of the document the diagnostics are published for.
      *
-     * @var int|null
+     * @var integer::*|null
      */
     public $version;
 
@@ -34,10 +34,10 @@ class PublishDiagnosticsParams
 
     /**
      * @param string $uri
-     * @param int|null $version
+     * @param integer::*|null $version
      * @param array<Diagnostic> $diagnostics
      */
-    public function __construct(string $uri, array $diagnostics, ?int $version = null)
+    public function __construct(string $uri, array $diagnostics, $version = null)
     {
         $this->uri = $uri;
         $this->version = $version;
diff --git a/src/RegularExpressionsClientCapabilities.php b/src/RegularExpressionsClientCapabilities.php
new file mode 100644
index 0000000..3888599
--- /dev/null
+++ b/src/RegularExpressionsClientCapabilities.php
@@ -0,0 +1,112 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Client capabilities specific to regular expressions.
+ */
+class RegularExpressionsClientCapabilities
+{
+    /**
+     * The engine's name.
+     *
+     * @var string
+     */
+    public $engine;
+
+    /**
+     * The engine's version.
+     *
+     * @var string|null
+     */
+    public $version;
+
+    /**
+     * @param string $engine
+     * @param string|null $version
+     */
+    public function __construct(string $engine, ?string $version = null)
+    {
+        $this->engine = $engine;
+        $this->version = $version;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'engine' => ['names' => [], 'iterable' => false],
+            'version' => ['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<string> $classNames
+     * @param array<string,mixed> $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/RenameClientCapabilities.php b/src/RenameClientCapabilities.php
index 95d1227..ec7db63 100644
--- a/src/RenameClientCapabilities.php
+++ b/src/RenameClientCapabilities.php
@@ -23,14 +23,39 @@ class RenameClientCapabilities
      */
     public $prepareSupport;
 
+    /**
+     * Client supports the default behavior result.
+     * 
+     * The value indicates the default behavior used by the
+     * client.
+     *
+     * @var PrepareSupportDefaultBehavior::*|null
+     */
+    public $prepareSupportDefaultBehavior;
+
+    /**
+     * Whether th client honors the change annotations in
+     * text edits and resource operations returned via the
+     * rename request's workspace edit by for example presenting
+     * the workspace edit in the user interface and asking
+     * for confirmation.
+     *
+     * @var bool|null
+     */
+    public $honorsChangeAnnotations;
+
     /**
      * @param bool|null $dynamicRegistration
      * @param bool|null $prepareSupport
+     * @param PrepareSupportDefaultBehavior::*|null $prepareSupportDefaultBehavior
+     * @param bool|null $honorsChangeAnnotations
      */
-    public function __construct(?bool $dynamicRegistration = null, ?bool $prepareSupport = null)
+    public function __construct(?bool $dynamicRegistration = null, ?bool $prepareSupport = null, $prepareSupportDefaultBehavior = null, ?bool $honorsChangeAnnotations = null)
     {
         $this->dynamicRegistration = $dynamicRegistration;
         $this->prepareSupport = $prepareSupport;
+        $this->prepareSupportDefaultBehavior = $prepareSupportDefaultBehavior;
+        $this->honorsChangeAnnotations = $honorsChangeAnnotations;
     }
 
     /**
@@ -42,6 +67,8 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
         $map = [
             'dynamicRegistration' => ['names' => [], 'iterable' => false],
             'prepareSupport' => ['names' => [], 'iterable' => false],
+            'prepareSupportDefaultBehavior' => ['names' => [], 'iterable' => false],
+            'honorsChangeAnnotations' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/RenameFile.php b/src/RenameFile.php
index c28597b..45d4018 100644
--- a/src/RenameFile.php
+++ b/src/RenameFile.php
@@ -14,6 +14,7 @@
 class RenameFile extends ResourceOperation
 {
     /**
+     * The resource operation kind.
      *
      * @var string
      */
@@ -40,18 +41,27 @@ class RenameFile extends ResourceOperation
      */
     public $options;
 
+    /**
+     * An optional annotation identifier describing the operation.
+     *
+     * @var string|null
+     */
+    public $annotationId;
+
     /**
      * @param string $kind
      * @param string $oldUri
      * @param string $newUri
      * @param RenameFileOptions|null $options
+     * @param string|null $annotationId
      */
-    public function __construct(string $kind, string $oldUri, string $newUri, ?RenameFileOptions $options = null)
+    public function __construct(string $kind, string $oldUri, string $newUri, ?RenameFileOptions $options = null, ?string $annotationId = null)
     {
         $this->kind = $kind;
         $this->oldUri = $oldUri;
         $this->newUri = $newUri;
         $this->options = $options;
+        $this->annotationId = $annotationId;
     }
 
     /**
@@ -65,6 +75,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'oldUri' => ['names' => [], 'iterable' => false],
             'newUri' => ['names' => [], 'iterable' => false],
             'options' => ['names' => [RenameFileOptions::class], 'iterable' => false],
+            'annotationId' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/RenameFilesParams.php b/src/RenameFilesParams.php
new file mode 100644
index 0000000..dd5dfc5
--- /dev/null
+++ b/src/RenameFilesParams.php
@@ -0,0 +1,103 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * The parameters sent in file rename requests/notifications.
+ */
+class RenameFilesParams
+{
+    /**
+     * An array of all files/folders renamed in this operation. When a folder is renamed, only
+     * the folder will be included, and not its children.
+     *
+     * @var array<FileRename>
+     */
+    public $files;
+
+    /**
+     * @param array<FileRename> $files
+     */
+    public function __construct(array $files)
+    {
+        $this->files = $files;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'files' => ['names' => [FileRename::class], 'iterable' => true],
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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/ResourceOperation.php b/src/ResourceOperation.php
index f0053cc..98ca44d 100644
--- a/src/ResourceOperation.php
+++ b/src/ResourceOperation.php
@@ -6,20 +6,33 @@
 use Exception;
 use RuntimeException;
 
+/**
+ * A generic resource operation.
+ */
 class ResourceOperation
 {
     /**
+     * The resource operation kind.
      *
      * @var string
      */
     public $kind;
 
+    /**
+     * An optional annotation identifier describing the operation.
+     *
+     * @var string|null
+     */
+    public $annotationId;
+
     /**
      * @param string $kind
+     * @param string|null $annotationId
      */
-    public function __construct(string $kind)
+    public function __construct(string $kind, ?string $annotationId = null)
     {
         $this->kind = $kind;
+        $this->annotationId = $annotationId;
     }
 
     /**
@@ -30,6 +43,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
     {
         $map = [
             'kind' => ['names' => [], 'iterable' => false],
+            'annotationId' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/SemanticTokens.php b/src/SemanticTokens.php
new file mode 100644
index 0000000..78c508f
--- /dev/null
+++ b/src/SemanticTokens.php
@@ -0,0 +1,114 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ */
+class SemanticTokens
+{
+    /**
+     * An optional result id. If provided and clients support delta updating
+     * the client will include the result id in the next semantic token request.
+     * A server can then instead of computing all semantic tokens again simply
+     * send a delta.
+     *
+     * @var string|null
+     */
+    public $resultId;
+
+    /**
+     * The actual tokens.
+     *
+     * @var array<int>
+     */
+    public $data;
+
+    /**
+     * @param string|null $resultId
+     * @param array<int> $data
+     */
+    public function __construct(array $data, ?string $resultId = null)
+    {
+        $this->resultId = $resultId;
+        $this->data = $data;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'resultId' => ['names' => [], 'iterable' => false],
+            'data' => ['names' => [], 'iterable' => true],
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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/SemanticTokensClientCapabilities.php b/src/SemanticTokensClientCapabilities.php
new file mode 100644
index 0000000..13994a1
--- /dev/null
+++ b/src/SemanticTokensClientCapabilities.php
@@ -0,0 +1,170 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ */
+class SemanticTokensClientCapabilities
+{
+    /**
+     * Whether implementation supports dynamic registration. If this is set to `true`
+     * the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
+     * return value for the corresponding server capability as well.
+     *
+     * @var bool|null
+     */
+    public $dynamicRegistration;
+
+    /**
+     * Which requests the client supports and might send to the server
+     * depending on the server's capability. Please note that clients might not
+     * show semantic tokens or degrade some of the user experience if a range
+     * or full request is advertised by the client but not provided by the
+     * server. If for example the client capability `requests.full` and
+     * `request.range` are both set to true but the server only provides a
+     * range provider the client might not render a minimap correctly or might
+     * even decide to not show any semantic tokens at all.
+     *
+     * @var array<mixed>
+     */
+    public $requests;
+
+    /**
+     * The token types that the client supports.
+     *
+     * @var array<string>
+     */
+    public $tokenTypes;
+
+    /**
+     * The token modifiers that the client supports.
+     *
+     * @var array<string>
+     */
+    public $tokenModifiers;
+
+    /**
+     * The token formats the clients supports.
+     *
+     * @var array<TokenFormat::*>
+     */
+    public $formats;
+
+    /**
+     * Whether the client supports tokens that can overlap each other.
+     *
+     * @var bool|null
+     */
+    public $overlappingTokenSupport;
+
+    /**
+     * Whether the client supports tokens that can span multiple lines.
+     *
+     * @var bool|null
+     */
+    public $multilineTokenSupport;
+
+    /**
+     * @param bool|null $dynamicRegistration
+     * @param array<mixed> $requests
+     * @param array<string> $tokenTypes
+     * @param array<string> $tokenModifiers
+     * @param array<TokenFormat::*> $formats
+     * @param bool|null $overlappingTokenSupport
+     * @param bool|null $multilineTokenSupport
+     */
+    public function __construct(array $requests, array $tokenTypes, array $tokenModifiers, array $formats, ?bool $dynamicRegistration = null, ?bool $overlappingTokenSupport = null, ?bool $multilineTokenSupport = null)
+    {
+        $this->dynamicRegistration = $dynamicRegistration;
+        $this->requests = $requests;
+        $this->tokenTypes = $tokenTypes;
+        $this->tokenModifiers = $tokenModifiers;
+        $this->formats = $formats;
+        $this->overlappingTokenSupport = $overlappingTokenSupport;
+        $this->multilineTokenSupport = $multilineTokenSupport;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'dynamicRegistration' => ['names' => [], 'iterable' => false],
+            'requests' => ['names' => [], 'iterable' => false],
+            'tokenTypes' => ['names' => [], 'iterable' => true],
+            'tokenModifiers' => ['names' => [], 'iterable' => true],
+            'formats' => ['names' => [], 'iterable' => true],
+            'overlappingTokenSupport' => ['names' => [], 'iterable' => false],
+            'multilineTokenSupport' => ['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<string> $classNames
+     * @param array<string,mixed> $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/SemanticTokensDelta.php b/src/SemanticTokensDelta.php
new file mode 100644
index 0000000..ec9e055
--- /dev/null
+++ b/src/SemanticTokensDelta.php
@@ -0,0 +1,110 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ */
+class SemanticTokensDelta
+{
+    /**
+     *
+     * @var string|null
+     */
+    public $resultId;
+
+    /**
+     * The semantic token edits to transform a previous result into a new result.
+     *
+     * @var array<SemanticTokensEdit>
+     */
+    public $edits;
+
+    /**
+     * @param string|null $resultId
+     * @param array<SemanticTokensEdit> $edits
+     */
+    public function __construct(array $edits, ?string $resultId = null)
+    {
+        $this->resultId = $resultId;
+        $this->edits = $edits;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'resultId' => ['names' => [], 'iterable' => false],
+            'edits' => ['names' => [SemanticTokensEdit::class], 'iterable' => true],
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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/SemanticTokensDeltaParams.php b/src/SemanticTokensDeltaParams.php
new file mode 100644
index 0000000..f0b3bc4
--- /dev/null
+++ b/src/SemanticTokensDeltaParams.php
@@ -0,0 +1,135 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ *
+ * Mixins (implemented TS interfaces): WorkDoneProgressParams, PartialResultParams
+ */
+class SemanticTokensDeltaParams extends WorkDoneProgressParams
+{
+    /**
+     * The text document.
+     *
+     * @var TextDocumentIdentifier
+     */
+    public $textDocument;
+
+    /**
+     * The result id of a previous response. The result Id can either point to a full response
+     * or a delta response depending on what was received last.
+     *
+     * @var string
+     */
+    public $previousResultId;
+
+    /**
+     * An optional token that a server can use to report work done progress.
+     *
+     * @var int|string|null
+     */
+    public $workDoneToken;
+
+    /**
+     * An optional token that a server can use to report partial results (e.g. streaming) to
+     * the client.
+     *
+     * @var int|string|null
+     */
+    public $partialResultToken;
+
+    /**
+     * @param TextDocumentIdentifier $textDocument
+     * @param string $previousResultId
+     * @param int|string|null $workDoneToken
+     * @param int|string|null $partialResultToken
+     */
+    public function __construct(TextDocumentIdentifier $textDocument, string $previousResultId, $workDoneToken = null, $partialResultToken = null)
+    {
+        $this->textDocument = $textDocument;
+        $this->previousResultId = $previousResultId;
+        $this->workDoneToken = $workDoneToken;
+        $this->partialResultToken = $partialResultToken;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'textDocument' => ['names' => [TextDocumentIdentifier::class], 'iterable' => false],
+            'previousResultId' => ['names' => [], '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<string> $classNames
+     * @param array<string,mixed> $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/SemanticTokensDeltaPartialResult.php b/src/SemanticTokensDeltaPartialResult.php
new file mode 100644
index 0000000..500f764
--- /dev/null
+++ b/src/SemanticTokensDeltaPartialResult.php
@@ -0,0 +1,100 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ */
+class SemanticTokensDeltaPartialResult
+{
+    /**
+     *
+     * @var array<SemanticTokensEdit>
+     */
+    public $edits;
+
+    /**
+     * @param array<SemanticTokensEdit> $edits
+     */
+    public function __construct(array $edits)
+    {
+        $this->edits = $edits;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'edits' => ['names' => [SemanticTokensEdit::class], 'iterable' => true],
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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/SemanticTokensDeltaRequest.php b/src/SemanticTokensDeltaRequest.php
new file mode 100644
index 0000000..adb6ed0
--- /dev/null
+++ b/src/SemanticTokensDeltaRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface SemanticTokensDeltaRequest
+{
+    public const METHOD = 'textDocument/semanticTokens/full/delta';
+}
\ No newline at end of file
diff --git a/src/SemanticTokensEdit.php b/src/SemanticTokensEdit.php
new file mode 100644
index 0000000..d44aa7e
--- /dev/null
+++ b/src/SemanticTokensEdit.php
@@ -0,0 +1,121 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ */
+class SemanticTokensEdit
+{
+    /**
+     * The start offset of the edit.
+     *
+     * @var int
+     */
+    public $start;
+
+    /**
+     * The count of elements to remove.
+     *
+     * @var int
+     */
+    public $deleteCount;
+
+    /**
+     * The elements to insert.
+     *
+     * @var array<int>|null
+     */
+    public $data;
+
+    /**
+     * @param int $start
+     * @param int $deleteCount
+     * @param array<int>|null $data
+     */
+    public function __construct(int $start, int $deleteCount, ?array $data = null)
+    {
+        $this->start = $start;
+        $this->deleteCount = $deleteCount;
+        $this->data = $data;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'start' => ['names' => [], 'iterable' => false],
+            'deleteCount' => ['names' => [], 'iterable' => false],
+            'data' => ['names' => [], 'iterable' => true],
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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/SemanticTokensLegend.php b/src/SemanticTokensLegend.php
new file mode 100644
index 0000000..9705136
--- /dev/null
+++ b/src/SemanticTokensLegend.php
@@ -0,0 +1,111 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ */
+class SemanticTokensLegend
+{
+    /**
+     * The token types a server uses.
+     *
+     * @var array<string>
+     */
+    public $tokenTypes;
+
+    /**
+     * The token modifiers a server uses.
+     *
+     * @var array<string>
+     */
+    public $tokenModifiers;
+
+    /**
+     * @param array<string> $tokenTypes
+     * @param array<string> $tokenModifiers
+     */
+    public function __construct(array $tokenTypes, array $tokenModifiers)
+    {
+        $this->tokenTypes = $tokenTypes;
+        $this->tokenModifiers = $tokenModifiers;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'tokenTypes' => ['names' => [], 'iterable' => true],
+            'tokenModifiers' => ['names' => [], 'iterable' => true],
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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/SemanticTokensOptions.php b/src/SemanticTokensOptions.php
new file mode 100644
index 0000000..366a045
--- /dev/null
+++ b/src/SemanticTokensOptions.php
@@ -0,0 +1,133 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ *
+ * Mixins (implemented TS interfaces): WorkDoneProgressOptions
+ */
+class SemanticTokensOptions extends WorkDoneProgressOptions
+{
+    /**
+     * The legend used by the server
+     *
+     * @var SemanticTokensLegend
+     */
+    public $legend;
+
+    /**
+     * Server supports providing semantic tokens for a specific range
+     * of a document.
+     *
+     * @var bool|array<mixed>|null
+     */
+    public $range;
+
+    /**
+     * Server supports providing semantic tokens for a full document.
+     *
+     * @var bool|array<mixed>|null
+     */
+    public $full;
+
+    /**
+     *
+     * @var bool|null
+     */
+    public $workDoneProgress;
+
+    /**
+     * @param SemanticTokensLegend $legend
+     * @param bool|array<mixed>|null $range
+     * @param bool|array<mixed>|null $full
+     * @param bool|null $workDoneProgress
+     */
+    public function __construct(SemanticTokensLegend $legend, $range = null, $full = null, ?bool $workDoneProgress = null)
+    {
+        $this->legend = $legend;
+        $this->range = $range;
+        $this->full = $full;
+        $this->workDoneProgress = $workDoneProgress;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'legend' => ['names' => [SemanticTokensLegend::class], 'iterable' => false],
+            'range' => ['names' => [], 'iterable' => false],
+            'full' => ['names' => [], 'iterable' => false],
+            '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<string> $classNames
+     * @param array<string,mixed> $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/SemanticTokensParams.php b/src/SemanticTokensParams.php
new file mode 100644
index 0000000..3c11649
--- /dev/null
+++ b/src/SemanticTokensParams.php
@@ -0,0 +1,124 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ *
+ * Mixins (implemented TS interfaces): WorkDoneProgressParams, PartialResultParams
+ */
+class SemanticTokensParams extends WorkDoneProgressParams
+{
+    /**
+     * The text document.
+     *
+     * @var TextDocumentIdentifier
+     */
+    public $textDocument;
+
+    /**
+     * An optional token that a server can use to report work done progress.
+     *
+     * @var int|string|null
+     */
+    public $workDoneToken;
+
+    /**
+     * An optional token that a server can use to report partial results (e.g. streaming) to
+     * the client.
+     *
+     * @var int|string|null
+     */
+    public $partialResultToken;
+
+    /**
+     * @param TextDocumentIdentifier $textDocument
+     * @param int|string|null $workDoneToken
+     * @param int|string|null $partialResultToken
+     */
+    public function __construct(TextDocumentIdentifier $textDocument, $workDoneToken = null, $partialResultToken = null)
+    {
+        $this->textDocument = $textDocument;
+        $this->workDoneToken = $workDoneToken;
+        $this->partialResultToken = $partialResultToken;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'textDocument' => ['names' => [TextDocumentIdentifier::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<string> $classNames
+     * @param array<string,mixed> $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/SemanticTokensPartialResult.php b/src/SemanticTokensPartialResult.php
new file mode 100644
index 0000000..fb1ab00
--- /dev/null
+++ b/src/SemanticTokensPartialResult.php
@@ -0,0 +1,100 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ */
+class SemanticTokensPartialResult
+{
+    /**
+     *
+     * @var array<int>
+     */
+    public $data;
+
+    /**
+     * @param array<int> $data
+     */
+    public function __construct(array $data)
+    {
+        $this->data = $data;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'data' => ['names' => [], 'iterable' => true],
+        ];
+
+        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<string> $classNames
+     * @param array<string,mixed> $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/SemanticTokensRangeParams.php b/src/SemanticTokensRangeParams.php
new file mode 100644
index 0000000..b9b331a
--- /dev/null
+++ b/src/SemanticTokensRangeParams.php
@@ -0,0 +1,134 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ *
+ * Mixins (implemented TS interfaces): WorkDoneProgressParams, PartialResultParams
+ */
+class SemanticTokensRangeParams extends WorkDoneProgressParams
+{
+    /**
+     * The text document.
+     *
+     * @var TextDocumentIdentifier
+     */
+    public $textDocument;
+
+    /**
+     * The range the semantic tokens are requested for.
+     *
+     * @var Range
+     */
+    public $range;
+
+    /**
+     * An optional token that a server can use to report work done progress.
+     *
+     * @var int|string|null
+     */
+    public $workDoneToken;
+
+    /**
+     * An optional token that a server can use to report partial results (e.g. streaming) to
+     * the client.
+     *
+     * @var int|string|null
+     */
+    public $partialResultToken;
+
+    /**
+     * @param TextDocumentIdentifier $textDocument
+     * @param Range $range
+     * @param int|string|null $workDoneToken
+     * @param int|string|null $partialResultToken
+     */
+    public function __construct(TextDocumentIdentifier $textDocument, Range $range, $workDoneToken = null, $partialResultToken = null)
+    {
+        $this->textDocument = $textDocument;
+        $this->range = $range;
+        $this->workDoneToken = $workDoneToken;
+        $this->partialResultToken = $partialResultToken;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'textDocument' => ['names' => [TextDocumentIdentifier::class], 'iterable' => false],
+            'range' => ['names' => [Range::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<string> $classNames
+     * @param array<string,mixed> $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/SemanticTokensRangeRequest.php b/src/SemanticTokensRangeRequest.php
new file mode 100644
index 0000000..b364e60
--- /dev/null
+++ b/src/SemanticTokensRangeRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface SemanticTokensRangeRequest
+{
+    public const METHOD = 'textDocument/semanticTokens/range';
+}
\ No newline at end of file
diff --git a/src/SemanticTokensRefreshRequest.php b/src/SemanticTokensRefreshRequest.php
new file mode 100644
index 0000000..b961731
--- /dev/null
+++ b/src/SemanticTokensRefreshRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface SemanticTokensRefreshRequest
+{
+    public const METHOD = `workspace/semanticTokens/refresh`;
+}
\ No newline at end of file
diff --git a/src/SemanticTokensRegistrationOptions.php b/src/SemanticTokensRegistrationOptions.php
new file mode 100644
index 0000000..713e1d1
--- /dev/null
+++ b/src/SemanticTokensRegistrationOptions.php
@@ -0,0 +1,155 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ *
+ * Mixins (implemented TS interfaces): TextDocumentRegistrationOptions, SemanticTokensOptions, StaticRegistrationOptions
+ */
+class SemanticTokensRegistrationOptions extends TextDocumentRegistrationOptions
+{
+    /**
+     * A document selector to identify the scope of the registration. If set to null
+     * the document selector provided on the client side will be used.
+     *
+     * @var array<(string|array<mixed>|array<mixed>|array<mixed>)>|null
+     */
+    public $documentSelector;
+
+    /**
+     * The legend used by the server
+     *
+     * @var SemanticTokensLegend
+     */
+    public $legend;
+
+    /**
+     * Server supports providing semantic tokens for a specific range
+     * of a document.
+     *
+     * @var bool|array<mixed>|null
+     */
+    public $range;
+
+    /**
+     * Server supports providing semantic tokens for a full document.
+     *
+     * @var bool|array<mixed>|null
+     */
+    public $full;
+
+    /**
+     *
+     * @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<mixed>|array<mixed>|array<mixed>)>|null $documentSelector
+     * @param SemanticTokensLegend $legend
+     * @param bool|array<mixed>|null $range
+     * @param bool|array<mixed>|null $full
+     * @param bool|null $workDoneProgress
+     * @param string|null $id
+     */
+    public function __construct(SemanticTokensLegend $legend, $documentSelector = null, $range = null, $full = null, ?bool $workDoneProgress = null, ?string $id = null)
+    {
+        $this->documentSelector = $documentSelector;
+        $this->legend = $legend;
+        $this->range = $range;
+        $this->full = $full;
+        $this->workDoneProgress = $workDoneProgress;
+        $this->id = $id;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'documentSelector' => ['names' => [], 'iterable' => false],
+            'legend' => ['names' => [SemanticTokensLegend::class], 'iterable' => false],
+            'range' => ['names' => [], 'iterable' => false],
+            'full' => ['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<string> $classNames
+     * @param array<string,mixed> $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/SemanticTokensRegistrationType.php b/src/SemanticTokensRegistrationType.php
new file mode 100644
index 0000000..ce389b0
--- /dev/null
+++ b/src/SemanticTokensRegistrationType.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface SemanticTokensRegistrationType
+{
+    public const METHOD = 'textDocument/semanticTokens';
+}
\ No newline at end of file
diff --git a/src/SemanticTokensRequest.php b/src/SemanticTokensRequest.php
new file mode 100644
index 0000000..a4ba33f
--- /dev/null
+++ b/src/SemanticTokensRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface SemanticTokensRequest
+{
+    public const METHOD = 'textDocument/semanticTokens/full';
+}
\ No newline at end of file
diff --git a/src/SemanticTokensWorkspaceClientCapabilities.php b/src/SemanticTokensWorkspaceClientCapabilities.php
new file mode 100644
index 0000000..897d2df
--- /dev/null
+++ b/src/SemanticTokensWorkspaceClientCapabilities.php
@@ -0,0 +1,105 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+class SemanticTokensWorkspaceClientCapabilities
+{
+    /**
+     * Whether the client implementation supports a refresh request sent from
+     * the server to the client.
+     * 
+     * Note that this event is global and will force the client to refresh all
+     * semantic tokens currently shown. It should be used with absolute care
+     * and is useful for situation where a server for example detect a project
+     * wide change that requires such a calculation.
+     *
+     * @var bool|null
+     */
+    public $refreshSupport;
+
+    /**
+     * @param bool|null $refreshSupport
+     */
+    public function __construct(?bool $refreshSupport = null)
+    {
+        $this->refreshSupport = $refreshSupport;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'refreshSupport' => ['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<string> $classNames
+     * @param array<string,mixed> $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 321cae4..edc57cc 100644
--- a/src/ServerCapabilities.php
+++ b/src/ServerCapabilities.php
@@ -178,11 +178,25 @@ class ServerCapabilities
     public $executeCommandProvider;
 
     /**
-     * Experimental server capabilities.
+     * The server provides call hierarchy support.
      *
-     * @var mixed|null
+     * @var bool|CallHierarchyOptions|CallHierarchyRegistrationOptions|null
      */
-    public $experimental;
+    public $callHierarchyProvider;
+
+    /**
+     * The server provides linked editing range support.
+     *
+     * @var bool|LinkedEditingRangeOptions|LinkedEditingRangeRegistrationOptions|null
+     */
+    public $linkedEditingRangeProvider;
+
+    /**
+     * The server provides semantic tokens support.
+     *
+     * @var SemanticTokensOptions|SemanticTokensRegistrationOptions|null
+     */
+    public $semanticTokensProvider;
 
     /**
      * The workspace server capabilities
@@ -191,6 +205,20 @@ class ServerCapabilities
      */
     public $workspace;
 
+    /**
+     * The server provides moniker support.
+     *
+     * @var bool|MonikerOptions|MonikerRegistrationOptions|null
+     */
+    public $monikerProvider;
+
+    /**
+     * Experimental server capabilities.
+     *
+     * @var mixed|null
+     */
+    public $experimental;
+
     /**
      * @param TextDocumentSyncOptions|TextDocumentSyncKind::*|null $textDocumentSync
      * @param CompletionOptions|null $completionProvider
@@ -215,10 +243,14 @@ class ServerCapabilities
      * @param bool|FoldingRangeOptions|FoldingRangeRegistrationOptions|null $foldingRangeProvider
      * @param bool|SelectionRangeOptions|SelectionRangeRegistrationOptions|null $selectionRangeProvider
      * @param ExecuteCommandOptions|null $executeCommandProvider
-     * @param mixed|null $experimental
+     * @param bool|CallHierarchyOptions|CallHierarchyRegistrationOptions|null $callHierarchyProvider
+     * @param bool|LinkedEditingRangeOptions|LinkedEditingRangeRegistrationOptions|null $linkedEditingRangeProvider
+     * @param SemanticTokensOptions|SemanticTokensRegistrationOptions|null $semanticTokensProvider
      * @param array<mixed>|null $workspace
+     * @param bool|MonikerOptions|MonikerRegistrationOptions|null $monikerProvider
+     * @param mixed|null $experimental
      */
-    public function __construct($textDocumentSync = null, ?CompletionOptions $completionProvider = null, $hoverProvider = null, ?SignatureHelpOptions $signatureHelpProvider = null, $declarationProvider = null, $definitionProvider = null, $typeDefinitionProvider = null, $implementationProvider = null, $referencesProvider = null, $documentHighlightProvider = null, $documentSymbolProvider = null, $codeActionProvider = null, ?CodeLensOptions $codeLensProvider = null, ?DocumentLinkOptions $documentLinkProvider = null, $colorProvider = null, $workspaceSymbolProvider = null, $documentFormattingProvider = null, $documentRangeFormattingProvider = null, ?DocumentOnTypeFormattingOptions $documentOnTypeFormattingProvider = null, $renameProvider = null, $foldingRangeProvider = null, $selectionRangeProvider = null, ?ExecuteCommandOptions $executeCommandProvider = null, $experimental = null, ?array $workspace = null)
+    public function __construct($textDocumentSync = null, ?CompletionOptions $completionProvider = null, $hoverProvider = null, ?SignatureHelpOptions $signatureHelpProvider = null, $declarationProvider = null, $definitionProvider = null, $typeDefinitionProvider = null, $implementationProvider = null, $referencesProvider = null, $documentHighlightProvider = null, $documentSymbolProvider = null, $codeActionProvider = null, ?CodeLensOptions $codeLensProvider = null, ?DocumentLinkOptions $documentLinkProvider = null, $colorProvider = null, $workspaceSymbolProvider = null, $documentFormattingProvider = null, $documentRangeFormattingProvider = null, ?DocumentOnTypeFormattingOptions $documentOnTypeFormattingProvider = null, $renameProvider = null, $foldingRangeProvider = null, $selectionRangeProvider = null, ?ExecuteCommandOptions $executeCommandProvider = null, $callHierarchyProvider = null, $linkedEditingRangeProvider = null, $semanticTokensProvider = null, ?array $workspace = null, $monikerProvider = null, $experimental = null)
     {
         $this->textDocumentSync = $textDocumentSync;
         $this->completionProvider = $completionProvider;
@@ -243,8 +275,12 @@ public function __construct($textDocumentSync = null, ?CompletionOptions $comple
         $this->foldingRangeProvider = $foldingRangeProvider;
         $this->selectionRangeProvider = $selectionRangeProvider;
         $this->executeCommandProvider = $executeCommandProvider;
-        $this->experimental = $experimental;
+        $this->callHierarchyProvider = $callHierarchyProvider;
+        $this->linkedEditingRangeProvider = $linkedEditingRangeProvider;
+        $this->semanticTokensProvider = $semanticTokensProvider;
         $this->workspace = $workspace;
+        $this->monikerProvider = $monikerProvider;
+        $this->experimental = $experimental;
     }
 
     /**
@@ -277,8 +313,12 @@ 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],
-            'experimental' => ['names' => [], 'iterable' => false],
+            'callHierarchyProvider' => ['names' => [CallHierarchyOptions::class, CallHierarchyRegistrationOptions::class], 'iterable' => false],
+            'linkedEditingRangeProvider' => ['names' => [LinkedEditingRangeOptions::class, LinkedEditingRangeRegistrationOptions::class], 'iterable' => false],
+            'semanticTokensProvider' => ['names' => [SemanticTokensOptions::class, SemanticTokensRegistrationOptions::class], 'iterable' => false],
             'workspace' => ['names' => [], 'iterable' => false],
+            'monikerProvider' => ['names' => [MonikerOptions::class, MonikerRegistrationOptions::class], 'iterable' => false],
+            'experimental' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/ShowDocumentClientCapabilities.php b/src/ShowDocumentClientCapabilities.php
new file mode 100644
index 0000000..4b85fc8
--- /dev/null
+++ b/src/ShowDocumentClientCapabilities.php
@@ -0,0 +1,103 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Client capabilities for the show document request.
+ */
+class ShowDocumentClientCapabilities
+{
+    /**
+     * The client has support for the show document
+     * request.
+     *
+     * @var bool
+     */
+    public $support;
+
+    /**
+     * @param bool $support
+     */
+    public function __construct(bool $support)
+    {
+        $this->support = $support;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'support' => ['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<string> $classNames
+     * @param array<string,mixed> $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/ShowDocumentParams.php b/src/ShowDocumentParams.php
new file mode 100644
index 0000000..702b6ea
--- /dev/null
+++ b/src/ShowDocumentParams.php
@@ -0,0 +1,140 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Params to show a document.
+ */
+class ShowDocumentParams
+{
+    /**
+     * The document uri to show.
+     *
+     * @var string
+     */
+    public $uri;
+
+    /**
+     * Indicates to show the resource in an external program.
+     * To show for example `https://code.visualstudio.com/`
+     * in the default WEB browser set `external` to `true`.
+     *
+     * @var bool|null
+     */
+    public $external;
+
+    /**
+     * An optional property to indicate whether the editor
+     * showing the document should take focus or not.
+     * Clients might ignore this property if an external
+     * program in started.
+     *
+     * @var bool|null
+     */
+    public $takeFocus;
+
+    /**
+     * An optional selection range if the document is a text
+     * document. Clients might ignore the property if an
+     * external program is started or the file is not a text
+     * file.
+     *
+     * @var Range|null
+     */
+    public $selection;
+
+    /**
+     * @param string $uri
+     * @param bool|null $external
+     * @param bool|null $takeFocus
+     * @param Range|null $selection
+     */
+    public function __construct(string $uri, ?bool $external = null, ?bool $takeFocus = null, ?Range $selection = null)
+    {
+        $this->uri = $uri;
+        $this->external = $external;
+        $this->takeFocus = $takeFocus;
+        $this->selection = $selection;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'uri' => ['names' => [], 'iterable' => false],
+            'external' => ['names' => [], 'iterable' => false],
+            'takeFocus' => ['names' => [], 'iterable' => false],
+            'selection' => ['names' => [Range::class], '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<string> $classNames
+     * @param array<string,mixed> $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/ShowDocumentRequest.php b/src/ShowDocumentRequest.php
new file mode 100644
index 0000000..424bb10
--- /dev/null
+++ b/src/ShowDocumentRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface ShowDocumentRequest
+{
+    public const METHOD = 'window/showDocument';
+}
\ No newline at end of file
diff --git a/src/ShowDocumentResult.php b/src/ShowDocumentResult.php
new file mode 100644
index 0000000..25b03a6
--- /dev/null
+++ b/src/ShowDocumentResult.php
@@ -0,0 +1,102 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * The result of an show document request.
+ */
+class ShowDocumentResult
+{
+    /**
+     * A boolean indicating if the show was successful.
+     *
+     * @var bool
+     */
+    public $success;
+
+    /**
+     * @param bool $success
+     */
+    public function __construct(bool $success)
+    {
+        $this->success = $success;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'success' => ['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<string> $classNames
+     * @param array<string,mixed> $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/ShowMessageRequestClientCapabilities.php b/src/ShowMessageRequestClientCapabilities.php
new file mode 100644
index 0000000..1ac23dd
--- /dev/null
+++ b/src/ShowMessageRequestClientCapabilities.php
@@ -0,0 +1,102 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+/**
+ * Show message request client capabilities
+ */
+class ShowMessageRequestClientCapabilities
+{
+    /**
+     * Capabilities specific to the `MessageActionItem` type.
+     *
+     * @var array<mixed>|null
+     */
+    public $messageActionItem;
+
+    /**
+     * @param array<mixed>|null $messageActionItem
+     */
+    public function __construct(?array $messageActionItem = null)
+    {
+        $this->messageActionItem = $messageActionItem;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'messageActionItem' => ['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<string> $classNames
+     * @param array<string,mixed> $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/SignatureHelpContext.php b/src/SignatureHelpContext.php
index 029ec98..218244b 100644
--- a/src/SignatureHelpContext.php
+++ b/src/SignatureHelpContext.php
@@ -30,7 +30,7 @@ class SignatureHelpContext
     /**
      * `true` if signature help was already showing when it was triggered.
      * 
-     * Retriggers occur when the signature help is already active and can be caused by actions such as
+     * Retrigger occurs when the signature help is already active and can be caused by actions such as
      * typing a trigger character, a cursor move, or document content changes.
      *
      * @var bool
diff --git a/src/SignatureInformation.php b/src/SignatureInformation.php
index 4140084..403c036 100644
--- a/src/SignatureInformation.php
+++ b/src/SignatureInformation.php
@@ -36,16 +36,27 @@ class SignatureInformation
      */
     public $parameters;
 
+    /**
+     * The index of the active parameter.
+     * 
+     * If provided, this is used in place of `SignatureHelp.activeParameter`.
+     *
+     * @var int|null
+     */
+    public $activeParameter;
+
     /**
      * @param string $label
      * @param string|MarkupContent|null $documentation
      * @param array<ParameterInformation>|null $parameters
+     * @param int|null $activeParameter
      */
-    public function __construct(string $label, $documentation = null, ?array $parameters = null)
+    public function __construct(string $label, $documentation = null, ?array $parameters = null, ?int $activeParameter = null)
     {
         $this->label = $label;
         $this->documentation = $documentation;
         $this->parameters = $parameters;
+        $this->activeParameter = $activeParameter;
     }
 
     /**
@@ -58,6 +69,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'label' => ['names' => [], 'iterable' => false],
             'documentation' => ['names' => [MarkupContent::class], 'iterable' => false],
             'parameters' => ['names' => [ParameterInformation::class], 'iterable' => true],
+            'activeParameter' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/SymbolInformation.php b/src/SymbolInformation.php
index 46928b3..7325d9e 100644
--- a/src/SymbolInformation.php
+++ b/src/SymbolInformation.php
@@ -26,6 +26,13 @@ class SymbolInformation
      */
     public $kind;
 
+    /**
+     * Tags for this completion item.
+     *
+     * @var array<SymbolTag::*>|null
+     */
+    public $tags;
+
     /**
      * Indicates if this symbol is deprecated.
      *
@@ -61,14 +68,16 @@ class SymbolInformation
     /**
      * @param string $name
      * @param SymbolKind::* $kind
+     * @param array<SymbolTag::*>|null $tags
      * @param bool|null $deprecated
      * @param Location $location
      * @param string|null $containerName
      */
-    public function __construct(string $name, $kind, Location $location, ?bool $deprecated = null, ?string $containerName = null)
+    public function __construct(string $name, $kind, Location $location, ?array $tags = null, ?bool $deprecated = null, ?string $containerName = null)
     {
         $this->name = $name;
         $this->kind = $kind;
+        $this->tags = $tags;
         $this->deprecated = $deprecated;
         $this->location = $location;
         $this->containerName = $containerName;
@@ -83,6 +92,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
         $map = [
             'name' => ['names' => [], 'iterable' => false],
             'kind' => ['names' => [], 'iterable' => false],
+            'tags' => ['names' => [], 'iterable' => true],
             'deprecated' => ['names' => [], 'iterable' => false],
             'location' => ['names' => [Location::class], 'iterable' => false],
             'containerName' => ['names' => [], 'iterable' => false],
diff --git a/src/TextDocument.php b/src/TextDocument.php
index 8569224..480bacf 100644
--- a/src/TextDocument.php
+++ b/src/TextDocument.php
@@ -32,7 +32,7 @@ class TextDocument
      * The version number of this document (it will increase after each
      * change, including undo/redo).
      *
-     * @var int
+     * @var integer::*
      */
     public $version;
 
@@ -46,10 +46,10 @@ class TextDocument
     /**
      * @param string $uri
      * @param string $languageId
-     * @param int $version
+     * @param integer::* $version
      * @param int $lineCount
      */
-    public function __construct(string $uri, string $languageId, int $version, int $lineCount)
+    public function __construct(string $uri, string $languageId, $version, int $lineCount)
     {
         $this->uri = $uri;
         $this->languageId = $languageId;
diff --git a/src/TextDocumentClientCapabilities.php b/src/TextDocumentClientCapabilities.php
index 31187eb..2f744c0 100644
--- a/src/TextDocumentClientCapabilities.php
+++ b/src/TextDocumentClientCapabilities.php
@@ -145,26 +145,54 @@ class TextDocumentClientCapabilities
     public $rename;
 
     /**
-     * Capabilities specific to `textDocument/foldingRange` requests.
+     * Capabilities specific to `textDocument/foldingRange` request.
      *
      * @var FoldingRangeClientCapabilities|null
      */
     public $foldingRange;
 
     /**
-     * Capabilities specific to `textDocument/selectionRange` requests
+     * Capabilities specific to `textDocument/selectionRange` request.
      *
      * @var SelectionRangeClientCapabilities|null
      */
     public $selectionRange;
 
     /**
-     * Capabilities specific to `textDocument/publishDiagnostics`.
+     * Capabilities specific to `textDocument/publishDiagnostics` notification.
      *
      * @var PublishDiagnosticsClientCapabilities|null
      */
     public $publishDiagnostics;
 
+    /**
+     * Capabilities specific to the various call hierarchy request.
+     *
+     * @var CallHierarchyClientCapabilities|null
+     */
+    public $callHierarchy;
+
+    /**
+     * Capabilities specific to the various semantic token request.
+     *
+     * @var SemanticTokensClientCapabilities|null
+     */
+    public $semanticTokens;
+
+    /**
+     * Capabilities specific to the linked editing range request.
+     *
+     * @var LinkedEditingRangeClientCapabilities|null
+     */
+    public $linkedEditingRange;
+
+    /**
+     * Client capabilities specific to the moniker request.
+     *
+     * @var MonikerClientCapabilities
+     */
+    public $moniker;
+
     /**
      * @param TextDocumentSyncClientCapabilities|null $synchronization
      * @param CompletionClientCapabilities|null $completion
@@ -188,8 +216,12 @@ class TextDocumentClientCapabilities
      * @param FoldingRangeClientCapabilities|null $foldingRange
      * @param SelectionRangeClientCapabilities|null $selectionRange
      * @param PublishDiagnosticsClientCapabilities|null $publishDiagnostics
+     * @param CallHierarchyClientCapabilities|null $callHierarchy
+     * @param SemanticTokensClientCapabilities|null $semanticTokens
+     * @param LinkedEditingRangeClientCapabilities|null $linkedEditingRange
+     * @param MonikerClientCapabilities $moniker
      */
-    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)
+    public function __construct(MonikerClientCapabilities $moniker, ?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, ?SemanticTokensClientCapabilities $semanticTokens = null, ?LinkedEditingRangeClientCapabilities $linkedEditingRange = null)
     {
         $this->synchronization = $synchronization;
         $this->completion = $completion;
@@ -213,6 +245,10 @@ public function __construct(?TextDocumentSyncClientCapabilities $synchronization
         $this->foldingRange = $foldingRange;
         $this->selectionRange = $selectionRange;
         $this->publishDiagnostics = $publishDiagnostics;
+        $this->callHierarchy = $callHierarchy;
+        $this->semanticTokens = $semanticTokens;
+        $this->linkedEditingRange = $linkedEditingRange;
+        $this->moniker = $moniker;
     }
 
     /**
@@ -244,6 +280,10 @@ 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' => [CallHierarchyClientCapabilities::class], 'iterable' => false],
+            'semanticTokens' => ['names' => [SemanticTokensClientCapabilities::class], 'iterable' => false],
+            'linkedEditingRange' => ['names' => [LinkedEditingRangeClientCapabilities::class], 'iterable' => false],
+            'moniker' => ['names' => [MonikerClientCapabilities::class], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/TextDocumentEdit.php b/src/TextDocumentEdit.php
index da4d706..b14a424 100644
--- a/src/TextDocumentEdit.php
+++ b/src/TextDocumentEdit.php
@@ -17,22 +17,22 @@ class TextDocumentEdit
     /**
      * The text document to change.
      *
-     * @var VersionedTextDocumentIdentifier
+     * @var OptionalVersionedTextDocumentIdentifier
      */
     public $textDocument;
 
     /**
      * The edits to be applied.
      *
-     * @var array<TextEdit>
+     * @var array<(TextEdit|AnnotatedTextEdit)>
      */
     public $edits;
 
     /**
-     * @param VersionedTextDocumentIdentifier $textDocument
-     * @param array<TextEdit> $edits
+     * @param OptionalVersionedTextDocumentIdentifier $textDocument
+     * @param array<(TextEdit|AnnotatedTextEdit)> $edits
      */
-    public function __construct(VersionedTextDocumentIdentifier $textDocument, array $edits)
+    public function __construct(OptionalVersionedTextDocumentIdentifier $textDocument, array $edits)
     {
         $this->textDocument = $textDocument;
         $this->edits = $edits;
@@ -45,8 +45,8 @@ public function __construct(VersionedTextDocumentIdentifier $textDocument, array
     public static function fromArray(array $array, bool $allowUnknownKeys = false)
     {
         $map = [
-            'textDocument' => ['names' => [VersionedTextDocumentIdentifier::class], 'iterable' => false],
-            'edits' => ['names' => [TextEdit::class], 'iterable' => true],
+            'textDocument' => ['names' => [OptionalVersionedTextDocumentIdentifier::class], 'iterable' => false],
+            'edits' => ['names' => [], 'iterable' => true],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/TextDocumentItem.php b/src/TextDocumentItem.php
index f8a900e..03a9b6e 100644
--- a/src/TextDocumentItem.php
+++ b/src/TextDocumentItem.php
@@ -30,7 +30,7 @@ class TextDocumentItem
      * The version number of this document (it will increase after each
      * change, including undo/redo).
      *
-     * @var int
+     * @var integer::*
      */
     public $version;
 
@@ -44,10 +44,10 @@ class TextDocumentItem
     /**
      * @param string $uri
      * @param string $languageId
-     * @param int $version
+     * @param integer::* $version
      * @param string $text
      */
-    public function __construct(string $uri, string $languageId, int $version, string $text)
+    public function __construct(string $uri, string $languageId, $version, string $text)
     {
         $this->uri = $uri;
         $this->languageId = $languageId;
diff --git a/src/TextDocumentSyncOptions.php b/src/TextDocumentSyncOptions.php
index b0640e2..21b2a22 100644
--- a/src/TextDocumentSyncOptions.php
+++ b/src/TextDocumentSyncOptions.php
@@ -44,7 +44,7 @@ class TextDocumentSyncOptions
      * If present save notifications are sent to the server. If omitted the notification should not be
      * sent.
      *
-     * @var SaveOptions|null
+     * @var bool|SaveOptions|null
      */
     public $save;
 
@@ -53,9 +53,9 @@ class TextDocumentSyncOptions
      * @param TextDocumentSyncKind::*|null $change
      * @param bool|null $willSave
      * @param bool|null $willSaveWaitUntil
-     * @param SaveOptions|null $save
+     * @param bool|SaveOptions|null $save
      */
-    public function __construct(?bool $openClose = null, $change = null, ?bool $willSave = null, ?bool $willSaveWaitUntil = null, ?SaveOptions $save = null)
+    public function __construct(?bool $openClose = null, $change = null, ?bool $willSave = null, ?bool $willSaveWaitUntil = null, $save = null)
     {
         $this->openClose = $openClose;
         $this->change = $change;
diff --git a/src/TokenFormat.php b/src/TokenFormat.php
new file mode 100644
index 0000000..65cd2c3
--- /dev/null
+++ b/src/TokenFormat.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface TokenFormat
+{
+    public const RELATIVE = 'relative';
+}
\ No newline at end of file
diff --git a/src/VersionedTextDocumentIdentifier.php b/src/VersionedTextDocumentIdentifier.php
index bc182bf..64f2744 100644
--- a/src/VersionedTextDocumentIdentifier.php
+++ b/src/VersionedTextDocumentIdentifier.php
@@ -7,20 +7,16 @@
 use RuntimeException;
 
 /**
- * An identifier to denote a specific version of a text document.
+ * A text document identifier to denote a specific version of a text document.
  *
  * Mixins (implemented TS interfaces): TextDocumentIdentifier
  */
 class VersionedTextDocumentIdentifier extends TextDocumentIdentifier
 {
     /**
-     * The version number of this document. If a versioned text document identifier
-     * is sent from the server to the client and the file is not open in the editor
-     * (the server has not received an open notification before) the server can send
-     * `null` to indicate that the version is unknown and the content on disk is the
-     * truth (as speced with document content ownership).
+     * The version number of this document.
      *
-     * @var int|null
+     * @var integer::*
      */
     public $version;
 
@@ -32,10 +28,10 @@ class VersionedTextDocumentIdentifier extends TextDocumentIdentifier
     public $uri;
 
     /**
-     * @param int|null $version
+     * @param integer::* $version
      * @param string $uri
      */
-    public function __construct(string $uri, $version = null)
+    public function __construct($version, string $uri)
     {
         $this->version = $version;
         $this->uri = $uri;
diff --git a/src/WillCreateFilesRequest.php b/src/WillCreateFilesRequest.php
new file mode 100644
index 0000000..d234478
--- /dev/null
+++ b/src/WillCreateFilesRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface WillCreateFilesRequest
+{
+    public const METHOD = 'workspace/willCreateFiles';
+}
\ No newline at end of file
diff --git a/src/WillDeleteFilesRequest.php b/src/WillDeleteFilesRequest.php
new file mode 100644
index 0000000..b064f3b
--- /dev/null
+++ b/src/WillDeleteFilesRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface WillDeleteFilesRequest
+{
+    public const METHOD = 'workspace/willDeleteFiles';
+}
\ No newline at end of file
diff --git a/src/WillRenameFilesRequest.php b/src/WillRenameFilesRequest.php
new file mode 100644
index 0000000..0c24a66
--- /dev/null
+++ b/src/WillRenameFilesRequest.php
@@ -0,0 +1,8 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface WillRenameFilesRequest
+{
+    public const METHOD = 'workspace/willRenameFiles';
+}
\ No newline at end of file
diff --git a/src/WindowClientCapabilities.php b/src/WindowClientCapabilities.php
new file mode 100644
index 0000000..93671c2
--- /dev/null
+++ b/src/WindowClientCapabilities.php
@@ -0,0 +1,121 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+use DTL\Invoke\Invoke;
+use Exception;
+use RuntimeException;
+
+class WindowClientCapabilities
+{
+    /**
+     * Whether client supports handling progress notifications. If set
+     * servers are allowed to report in `workDoneProgress` property in the
+     * request specific server capabilities.
+     *
+     * @var bool|null
+     */
+    public $workDoneProgress;
+
+    /**
+     * Capabilities specific to the showMessage request.
+     *
+     * @var ShowMessageRequestClientCapabilities|null
+     */
+    public $showMessage;
+
+    /**
+     * Capabilities specific to the showDocument request.
+     *
+     * @var ShowDocumentClientCapabilities|null
+     */
+    public $showDocument;
+
+    /**
+     * @param bool|null $workDoneProgress
+     * @param ShowMessageRequestClientCapabilities|null $showMessage
+     * @param ShowDocumentClientCapabilities|null $showDocument
+     */
+    public function __construct(?bool $workDoneProgress = null, ?ShowMessageRequestClientCapabilities $showMessage = null, ?ShowDocumentClientCapabilities $showDocument = null)
+    {
+        $this->workDoneProgress = $workDoneProgress;
+        $this->showMessage = $showMessage;
+        $this->showDocument = $showDocument;
+    }
+
+    /**
+     * @param array<string,mixed> $array
+     * @return static
+     */
+    public static function fromArray(array $array, bool $allowUnknownKeys = false)
+    {
+        $map = [
+            'workDoneProgress' => ['names' => [], 'iterable' => false],
+            'showMessage' => ['names' => [ShowMessageRequestClientCapabilities::class], 'iterable' => false],
+            'showDocument' => ['names' => [ShowDocumentClientCapabilities::class], '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<string> $classNames
+     * @param array<string,mixed> $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/WorkDoneProgressBegin.php b/src/WorkDoneProgressBegin.php
index 1de8bec..398a200 100644
--- a/src/WorkDoneProgressBegin.php
+++ b/src/WorkDoneProgressBegin.php
@@ -50,7 +50,7 @@ class WorkDoneProgressBegin
      * to ignore the `percentage` value in subsequent in report notifications.
      * 
      * The value should be steadily rising. Clients are free to ignore values
-     * that are not following this rule.
+     * that are not following this rule. The value range is [0, 100].
      *
      * @var int|null
      */
diff --git a/src/WorkDoneProgressReport.php b/src/WorkDoneProgressReport.php
index 7b666bf..db45d09 100644
--- a/src/WorkDoneProgressReport.php
+++ b/src/WorkDoneProgressReport.php
@@ -15,11 +15,10 @@ class WorkDoneProgressReport
     public $kind;
 
     /**
-     * Controls enablement state of a cancel button. This property is only valid if a cancel
-     * button got requested in the `WorkDoneProgressStart` payload.
+     * Controls enablement state of a cancel button.
      * 
-     * Clients that don't support cancellation or don't support control the button's
-     * enablement state are allowed to ignore the setting.
+     * Clients that don't support cancellation or don't support controlling the button's
+     * enablement state are allowed to ignore the property.
      *
      * @var bool|null
      */
@@ -42,7 +41,7 @@ class WorkDoneProgressReport
      * to ignore the `percentage` value in subsequent in report notifications.
      * 
      * The value should be steadily rising. Clients are free to ignore values
-     * that are not following this rule.
+     * that are not following this rule. The value range is [0, 100]
      *
      * @var int|null
      */
diff --git a/src/WorkspaceClientCapabilities.php b/src/WorkspaceClientCapabilities.php
index 1400f6f..b4380cd 100644
--- a/src/WorkspaceClientCapabilities.php
+++ b/src/WorkspaceClientCapabilities.php
@@ -55,6 +55,31 @@ class WorkspaceClientCapabilities
      */
     public $executeCommand;
 
+    /**
+     * Capabilities specific to the semantic token requests scoped to the
+     * workspace.
+     *
+     * @var SemanticTokensWorkspaceClientCapabilities|null
+     */
+    public $semanticTokens;
+
+    /**
+     * Capabilities specific to the code lens requests scoped to the
+     * workspace.
+     *
+     * @var CodeLensWorkspaceClientCapabilities|null
+     */
+    public $codeLens;
+
+    /**
+     * The client has support for file notifications/requests for user operations on files.
+     * 
+     * Since 3.16.0
+     *
+     * @var FileOperationClientCapabilities|null
+     */
+    public $fileOperations;
+
     /**
      * @param bool|null $applyEdit
      * @param WorkspaceEditClientCapabilities|null $workspaceEdit
@@ -62,8 +87,11 @@ class WorkspaceClientCapabilities
      * @param DidChangeWatchedFilesClientCapabilities|null $didChangeWatchedFiles
      * @param WorkspaceSymbolClientCapabilities|null $symbol
      * @param ExecuteCommandClientCapabilities|null $executeCommand
+     * @param SemanticTokensWorkspaceClientCapabilities|null $semanticTokens
+     * @param CodeLensWorkspaceClientCapabilities|null $codeLens
+     * @param FileOperationClientCapabilities|null $fileOperations
      */
-    public function __construct(?bool $applyEdit = null, ?WorkspaceEditClientCapabilities $workspaceEdit = null, ?DidChangeConfigurationClientCapabilities $didChangeConfiguration = null, ?DidChangeWatchedFilesClientCapabilities $didChangeWatchedFiles = null, ?WorkspaceSymbolClientCapabilities $symbol = null, ?ExecuteCommandClientCapabilities $executeCommand = null)
+    public function __construct(?bool $applyEdit = null, ?WorkspaceEditClientCapabilities $workspaceEdit = null, ?DidChangeConfigurationClientCapabilities $didChangeConfiguration = null, ?DidChangeWatchedFilesClientCapabilities $didChangeWatchedFiles = null, ?WorkspaceSymbolClientCapabilities $symbol = null, ?ExecuteCommandClientCapabilities $executeCommand = null, ?SemanticTokensWorkspaceClientCapabilities $semanticTokens = null, ?CodeLensWorkspaceClientCapabilities $codeLens = null, ?FileOperationClientCapabilities $fileOperations = null)
     {
         $this->applyEdit = $applyEdit;
         $this->workspaceEdit = $workspaceEdit;
@@ -71,6 +99,9 @@ public function __construct(?bool $applyEdit = null, ?WorkspaceEditClientCapabil
         $this->didChangeWatchedFiles = $didChangeWatchedFiles;
         $this->symbol = $symbol;
         $this->executeCommand = $executeCommand;
+        $this->semanticTokens = $semanticTokens;
+        $this->codeLens = $codeLens;
+        $this->fileOperations = $fileOperations;
     }
 
     /**
@@ -86,6 +117,9 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'didChangeWatchedFiles' => ['names' => [DidChangeWatchedFilesClientCapabilities::class], 'iterable' => false],
             'symbol' => ['names' => [WorkspaceSymbolClientCapabilities::class], 'iterable' => false],
             'executeCommand' => ['names' => [ExecuteCommandClientCapabilities::class], 'iterable' => false],
+            'semanticTokens' => ['names' => [SemanticTokensWorkspaceClientCapabilities::class], 'iterable' => false],
+            'codeLens' => ['names' => [CodeLensWorkspaceClientCapabilities::class], 'iterable' => false],
+            'fileOperations' => ['names' => [FileOperationClientCapabilities::class], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/WorkspaceEdit.php b/src/WorkspaceEdit.php
index 6dac33a..db5d589 100644
--- a/src/WorkspaceEdit.php
+++ b/src/WorkspaceEdit.php
@@ -36,14 +36,26 @@ class WorkspaceEdit
      */
     public $documentChanges;
 
+    /**
+     * A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and
+     * delete file / folder operations.
+     * 
+     * Whether clients honor this property depends on the client capability `workspace.changeAnnotationSupport`.
+     *
+     * @var array<mixed>|null
+     */
+    public $changeAnnotations;
+
     /**
      * @param array<mixed>|null $changes
      * @param array<(TextDocumentEdit|CreateFile|RenameFile|DeleteFile)>|null $documentChanges
+     * @param array<mixed>|null $changeAnnotations
      */
-    public function __construct(?array $changes = null, ?array $documentChanges = null)
+    public function __construct(?array $changes = null, ?array $documentChanges = null, ?array $changeAnnotations = null)
     {
         $this->changes = $changes;
         $this->documentChanges = $documentChanges;
+        $this->changeAnnotations = $changeAnnotations;
     }
 
     /**
@@ -55,6 +67,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
         $map = [
             'changes' => ['names' => [], 'iterable' => false],
             'documentChanges' => ['names' => [], 'iterable' => true],
+            'changeAnnotations' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/WorkspaceEditClientCapabilities.php b/src/WorkspaceEditClientCapabilities.php
index ab41654..4a29c78 100644
--- a/src/WorkspaceEditClientCapabilities.php
+++ b/src/WorkspaceEditClientCapabilities.php
@@ -31,16 +31,39 @@ class WorkspaceEditClientCapabilities
      */
     public $failureHandling;
 
+    /**
+     * Whether the client normalizes line endings to the client specific
+     * setting.
+     * If set to `true` the client will normalize line ending characters
+     * in a workspace edit containing to the client specific new line
+     * character.
+     *
+     * @var bool|null
+     */
+    public $normalizesLineEndings;
+
+    /**
+     * Whether the client in general supports change annotations on text edits,
+     * create file, rename file and delete file changes.
+     *
+     * @var array<mixed>|null
+     */
+    public $changeAnnotationSupport;
+
     /**
      * @param bool|null $documentChanges
      * @param array<'create'|'rename'|'delete'>|null $resourceOperations
      * @param 'abort'|'transactional'|'undo'|'textOnlyTransactional'|null $failureHandling
+     * @param bool|null $normalizesLineEndings
+     * @param array<mixed>|null $changeAnnotationSupport
      */
-    public function __construct(?bool $documentChanges = null, ?array $resourceOperations = null, $failureHandling = null)
+    public function __construct(?bool $documentChanges = null, ?array $resourceOperations = null, $failureHandling = null, ?bool $normalizesLineEndings = null, ?array $changeAnnotationSupport = null)
     {
         $this->documentChanges = $documentChanges;
         $this->resourceOperations = $resourceOperations;
         $this->failureHandling = $failureHandling;
+        $this->normalizesLineEndings = $normalizesLineEndings;
+        $this->changeAnnotationSupport = $changeAnnotationSupport;
     }
 
     /**
@@ -53,6 +76,8 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
             'documentChanges' => ['names' => [], 'iterable' => false],
             'resourceOperations' => ['names' => [], 'iterable' => true],
             'failureHandling' => ['names' => [], 'iterable' => false],
+            'normalizesLineEndings' => ['names' => [], 'iterable' => false],
+            'changeAnnotationSupport' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/WorkspaceSymbolClientCapabilities.php b/src/WorkspaceSymbolClientCapabilities.php
index 820419c..101e7c6 100644
--- a/src/WorkspaceSymbolClientCapabilities.php
+++ b/src/WorkspaceSymbolClientCapabilities.php
@@ -25,14 +25,24 @@ class WorkspaceSymbolClientCapabilities
      */
     public $symbolKind;
 
+    /**
+     * The client supports tags on `SymbolInformation`.
+     * Clients supporting tags have to handle unknown tags gracefully.
+     *
+     * @var array<mixed>|null
+     */
+    public $tagSupport;
+
     /**
      * @param bool|null $dynamicRegistration
      * @param array<mixed>|null $symbolKind
+     * @param array<mixed>|null $tagSupport
      */
-    public function __construct(?bool $dynamicRegistration = null, ?array $symbolKind = null)
+    public function __construct(?bool $dynamicRegistration = null, ?array $symbolKind = null, ?array $tagSupport = null)
     {
         $this->dynamicRegistration = $dynamicRegistration;
         $this->symbolKind = $symbolKind;
+        $this->tagSupport = $tagSupport;
     }
 
     /**
@@ -44,6 +54,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
         $map = [
             'dynamicRegistration' => ['names' => [], 'iterable' => false],
             'symbolKind' => ['names' => [], 'iterable' => false],
+            'tagSupport' => ['names' => [], 'iterable' => false],
         ];
 
         foreach ($array as $key => &$value) {
diff --git a/src/_ClientCapabilities.php b/src/_ClientCapabilities.php
index d0a1cb3..0ef3ad8 100644
--- a/src/_ClientCapabilities.php
+++ b/src/_ClientCapabilities.php
@@ -28,10 +28,17 @@ class _ClientCapabilities
     /**
      * Window specific client capabilities.
      *
-     * @var array<mixed>|null
+     * @var WindowClientCapabilities|null
      */
     public $window;
 
+    /**
+     * General client capabilities.
+     *
+     * @var GeneralClientCapabilities|null
+     */
+    public $general;
+
     /**
      * Experimental client capabilities.
      *
@@ -42,14 +49,16 @@ class _ClientCapabilities
     /**
      * @param WorkspaceClientCapabilities|null $workspace
      * @param TextDocumentClientCapabilities|null $textDocument
-     * @param array<mixed>|null $window
+     * @param WindowClientCapabilities|null $window
+     * @param GeneralClientCapabilities|null $general
      * @param array<mixed>|null $experimental
      */
-    public function __construct(?WorkspaceClientCapabilities $workspace = null, ?TextDocumentClientCapabilities $textDocument = null, ?array $window = null, ?array $experimental = null)
+    public function __construct(?WorkspaceClientCapabilities $workspace = null, ?TextDocumentClientCapabilities $textDocument = null, ?WindowClientCapabilities $window = null, ?GeneralClientCapabilities $general = null, ?array $experimental = null)
     {
         $this->workspace = $workspace;
         $this->textDocument = $textDocument;
         $this->window = $window;
+        $this->general = $general;
         $this->experimental = $experimental;
     }
 
@@ -62,7 +71,8 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
         $map = [
             'workspace' => ['names' => [WorkspaceClientCapabilities::class], 'iterable' => false],
             'textDocument' => ['names' => [TextDocumentClientCapabilities::class], 'iterable' => false],
-            'window' => ['names' => [], 'iterable' => false],
+            'window' => ['names' => [WindowClientCapabilities::class], 'iterable' => false],
+            'general' => ['names' => [GeneralClientCapabilities::class], 'iterable' => false],
             'experimental' => ['names' => [], 'iterable' => false],
         ];
 
diff --git a/src/_InitializeParams.php b/src/_InitializeParams.php
index 009da2f..b776b66 100644
--- a/src/_InitializeParams.php
+++ b/src/_InitializeParams.php
@@ -17,7 +17,7 @@ class _InitializeParams extends WorkDoneProgressParams
      * The process Id of the parent process that started
      * the server.
      *
-     * @var int|null
+     * @var integer::*|null
      */
     public $processId;
 
@@ -28,6 +28,18 @@ class _InitializeParams extends WorkDoneProgressParams
      */
     public $clientInfo;
 
+    /**
+     * The locale the client is currently showing the user interface
+     * in. This must not necessarily be the locale of the operating
+     * system.
+     * 
+     * Uses IETF language tags as the value's syntax
+     * (See https://en.wikipedia.org/wiki/IETF_language_tag)
+     *
+     * @var string|null
+     */
+    public $locale;
+
     /**
      * The rootPath of the workspace. Is null
      * if no folder is open.
@@ -74,8 +86,9 @@ class _InitializeParams extends WorkDoneProgressParams
     public $workDoneToken;
 
     /**
-     * @param int|null $processId
+     * @param integer::*|null $processId
      * @param array<mixed>|null $clientInfo
+     * @param string|null $locale
      * @param string|null $rootPath
      * @param string|null $rootUri
      * @param ClientCapabilities $capabilities
@@ -83,10 +96,11 @@ class _InitializeParams extends WorkDoneProgressParams
      * @param 'off'|'messages'|'verbose'|null $trace
      * @param int|string|null $workDoneToken
      */
-    public function __construct(ClientCapabilities $capabilities, $processId = null, ?array $clientInfo = null, $rootPath = null, $rootUri = null, $initializationOptions = null, $trace = null, $workDoneToken = null)
+    public function __construct(ClientCapabilities $capabilities, $processId = null, ?array $clientInfo = null, ?string $locale = null, $rootPath = null, $rootUri = null, $initializationOptions = null, $trace = null, $workDoneToken = null)
     {
         $this->processId = $processId;
         $this->clientInfo = $clientInfo;
+        $this->locale = $locale;
         $this->rootPath = $rootPath;
         $this->rootUri = $rootUri;
         $this->capabilities = $capabilities;
@@ -104,6 +118,7 @@ public static function fromArray(array $array, bool $allowUnknownKeys = false)
         $map = [
             'processId' => ['names' => [], 'iterable' => false],
             'clientInfo' => ['names' => [], 'iterable' => false],
+            'locale' => ['names' => [], 'iterable' => false],
             'rootPath' => ['names' => [], 'iterable' => false],
             'rootUri' => ['names' => [], 'iterable' => false],
             'capabilities' => ['names' => [ClientCapabilities::class], 'iterable' => false],
diff --git a/src/_ServerCapabilities.php b/src/_ServerCapabilities.php
index c0a8b86..c381f50 100644
--- a/src/_ServerCapabilities.php
+++ b/src/_ServerCapabilities.php
@@ -178,6 +178,41 @@ class _ServerCapabilities
      */
     public $executeCommandProvider;
 
+    /**
+     * The server provides call hierarchy support.
+     *
+     * @var bool|CallHierarchyOptions|CallHierarchyRegistrationOptions|null
+     */
+    public $callHierarchyProvider;
+
+    /**
+     * The server provides linked editing range support.
+     *
+     * @var bool|LinkedEditingRangeOptions|LinkedEditingRangeRegistrationOptions|null
+     */
+    public $linkedEditingRangeProvider;
+
+    /**
+     * The server provides semantic tokens support.
+     *
+     * @var SemanticTokensOptions|SemanticTokensRegistrationOptions|null
+     */
+    public $semanticTokensProvider;
+
+    /**
+     * Window specific server capabilities.
+     *
+     * @var array<mixed>|null
+     */
+    public $workspace;
+
+    /**
+     * The server provides moniker support.
+     *
+     * @var bool|MonikerOptions|MonikerRegistrationOptions|null
+     */
+    public $monikerProvider;
+
     /**
      * Experimental server capabilities.
      *
@@ -209,9 +244,14 @@ class _ServerCapabilities
      * @param bool|FoldingRangeOptions|FoldingRangeRegistrationOptions|null $foldingRangeProvider
      * @param bool|SelectionRangeOptions|SelectionRangeRegistrationOptions|null $selectionRangeProvider
      * @param ExecuteCommandOptions|null $executeCommandProvider
+     * @param bool|CallHierarchyOptions|CallHierarchyRegistrationOptions|null $callHierarchyProvider
+     * @param bool|LinkedEditingRangeOptions|LinkedEditingRangeRegistrationOptions|null $linkedEditingRangeProvider
+     * @param SemanticTokensOptions|SemanticTokensRegistrationOptions|null $semanticTokensProvider
+     * @param array<mixed>|null $workspace
+     * @param bool|MonikerOptions|MonikerRegistrationOptions|null $monikerProvider
      * @param mixed|null $experimental
      */
-    public function __construct($textDocumentSync = null, ?CompletionOptions $completionProvider = null, $hoverProvider = null, ?SignatureHelpOptions $signatureHelpProvider = null, $declarationProvider = null, $definitionProvider = null, $typeDefinitionProvider = null, $implementationProvider = null, $referencesProvider = null, $documentHighlightProvider = null, $documentSymbolProvider = null, $codeActionProvider = null, ?CodeLensOptions $codeLensProvider = null, ?DocumentLinkOptions $documentLinkProvider = null, $colorProvider = null, $workspaceSymbolProvider = null, $documentFormattingProvider = null, $documentRangeFormattingProvider = null, ?DocumentOnTypeFormattingOptions $documentOnTypeFormattingProvider = null, $renameProvider = null, $foldingRangeProvider = null, $selectionRangeProvider = null, ?ExecuteCommandOptions $executeCommandProvider = null, $experimental = null)
+    public function __construct($textDocumentSync = null, ?CompletionOptions $completionProvider = null, $hoverProvider = null, ?SignatureHelpOptions $signatureHelpProvider = null, $declarationProvider = null, $definitionProvider = null, $typeDefinitionProvider = null, $implementationProvider = null, $referencesProvider = null, $documentHighlightProvider = null, $documentSymbolProvider = null, $codeActionProvider = null, ?CodeLensOptions $codeLensProvider = null, ?DocumentLinkOptions $documentLinkProvider = null, $colorProvider = null, $workspaceSymbolProvider = null, $documentFormattingProvider = null, $documentRangeFormattingProvider = null, ?DocumentOnTypeFormattingOptions $documentOnTypeFormattingProvider = null, $renameProvider = null, $foldingRangeProvider = null, $selectionRangeProvider = null, ?ExecuteCommandOptions $executeCommandProvider = null, $callHierarchyProvider = null, $linkedEditingRangeProvider = null, $semanticTokensProvider = null, ?array $workspace = null, $monikerProvider = null, $experimental = null)
     {
         $this->textDocumentSync = $textDocumentSync;
         $this->completionProvider = $completionProvider;
@@ -236,6 +276,11 @@ public function __construct($textDocumentSync = null, ?CompletionOptions $comple
         $this->foldingRangeProvider = $foldingRangeProvider;
         $this->selectionRangeProvider = $selectionRangeProvider;
         $this->executeCommandProvider = $executeCommandProvider;
+        $this->callHierarchyProvider = $callHierarchyProvider;
+        $this->linkedEditingRangeProvider = $linkedEditingRangeProvider;
+        $this->semanticTokensProvider = $semanticTokensProvider;
+        $this->workspace = $workspace;
+        $this->monikerProvider = $monikerProvider;
         $this->experimental = $experimental;
     }
 
@@ -269,6 +314,11 @@ 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' => [CallHierarchyOptions::class, CallHierarchyRegistrationOptions::class], 'iterable' => false],
+            'linkedEditingRangeProvider' => ['names' => [LinkedEditingRangeOptions::class, LinkedEditingRangeRegistrationOptions::class], 'iterable' => false],
+            'semanticTokensProvider' => ['names' => [SemanticTokensOptions::class, SemanticTokensRegistrationOptions::class], 'iterable' => false],
+            'workspace' => ['names' => [], 'iterable' => false],
+            'monikerProvider' => ['names' => [MonikerOptions::class, MonikerRegistrationOptions::class], 'iterable' => false],
             'experimental' => ['names' => [], 'iterable' => false],
         ];
 
diff --git a/src/integer.php b/src/integer.php
new file mode 100644
index 0000000..7249212
--- /dev/null
+++ b/src/integer.php
@@ -0,0 +1,9 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface integer
+{
+    public const MIN_VALUE = -2147483648;
+    public const MAX_VALUE = 2147483647;
+}
\ No newline at end of file
diff --git a/src/uinteger.php b/src/uinteger.php
new file mode 100644
index 0000000..0ec101c
--- /dev/null
+++ b/src/uinteger.php
@@ -0,0 +1,9 @@
+<?php // Auto-generated from vscode-languageserver-protocol (typescript)
+
+namespace Phpactor\LanguageServerProtocol;
+
+interface uinteger
+{
+    public const MIN_VALUE = 0;
+    public const MAX_VALUE = 2147483647;
+}
\ No newline at end of file
diff --git a/ts/renderer.ts b/ts/renderer.ts
index 5265722..735ec90 100644
--- a/ts/renderer.ts
+++ b/ts/renderer.ts
@@ -1,5 +1,6 @@
 import {PhpClass, Property, PhpClassLike, isPhpClass, isPhpInterface, PhpInterface, PhpConstant} from './phpClass';
 import * as inflect from 'inflect';
+import {isUndefined} from 'util';
 
 export class Renderer
 {
@@ -46,9 +47,9 @@ export class Renderer
 
         if (phpClass.mixins.length > 0 || phpClass.docs.length > 0) {
             source.push(`/**`);
-            phpClass.docs.forEach((line: string) => {
-                source.push(` * ${line}`);
-            });
+
+            this.renderDocs(phpClass.docs, source, ' ')
+
             if (phpClass.mixins.length > 0 && phpClass.docs.length > 0) {
                 source.push(` *`);
             }
@@ -75,12 +76,23 @@ export class Renderer
         return source.join("\n");
     }
 
+    renderDocs(docs: string[], source: string[], indent: string): string[] {
+        docs.forEach((line: string) => {
+            if (isUndefined(line)) {
+                return;
+            }
+            line.split("\n").forEach((lineLine: string) => {
+                source.push(indent + `* ${lineLine}`);
+            });
+        });
+
+        return source;
+    }
+
     buildProperties(declaration: PhpClass, source: string[]): void {
         declaration.properties.forEach((property: Property) => {
             source.push(`    /**`);
-            for (const docLine of property.docs) {
-                source.push(`     * ${docLine}`);
-            }
+            this.renderDocs(property.docs, source, '     ');
             source.push(`     *`);
             source.push(`     * @var ${this.renderPropertyType(property)}`);
             source.push(`     */`);
@@ -205,7 +217,7 @@ export class Renderer
         });
 
         classResolutionSource.push('        ];'),
-        classResolutionSource.push(`
+            classResolutionSource.push(`
         foreach ($array as $key => &$value) {
             if (!isset($map[$key])) {
                 if ($allowUnknownKeys) {
diff --git a/ts/transpile.ts b/ts/transpile.ts
index 91f7b9f..e25730b 100644
--- a/ts/transpile.ts
+++ b/ts/transpile.ts
@@ -9,16 +9,22 @@ import * as path from 'path';
 import {createNodeMap} from './nodeMap';
 
 const paths: string[] = [
-    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'protocol.d.ts'),
-    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'protocol.foldingRange.d.ts'),
-    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'protocol.workspaceFolders.d.ts'),
-    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'protocol.progress.d.ts'),
-    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'protocol.colorProvider.d.ts'),
-    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'protocol.configuration.d.ts'),
-    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'protocol.declaration.d.ts'),
-    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'protocol.typeDefinition.d.ts'),
-    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'protocol.implementation.d.ts'),
-    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'protocol.selectionRange.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.callHierarchy.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.colorProvider.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.configuration.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.declaration.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.fileOperations.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.foldingRange.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.implementation.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.linkedEditingRange.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.moniker.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.progress.d.ts'),
+    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.semanticTokens.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.showDocument.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.typeDefinition.d.ts'),
+    path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-protocol', 'lib', 'common', 'protocol.workspaceFolders.d.ts'),
     path.resolve(__dirname, '..', 'node_modules', 'vscode-languageserver-types', 'lib', 'umd', 'main.d.ts'),
     path.resolve(__dirname, '../ts/stubs.ts'),
 ];
diff --git a/ts/typeConverter.ts b/ts/typeConverter.ts
index 173e795..b356f0c 100644
--- a/ts/typeConverter.ts
+++ b/ts/typeConverter.ts
@@ -106,6 +106,10 @@ export class TypeConverter
         if (isTypeReferenceNode(type) && isIdentifier(type.typeName)) {
             const typeName = type.typeName.escapedText.toString();
 
+            if (type.typeName.escapedText === 'uinteger') {
+                return new PhpType('int', 'int');
+            }
+
             if (this.nodeMap.modules.has(typeName)) {
                 return new PhpType(null, typeName + '::*');
             }
