diff --git a/.doctrine-project.json b/.doctrine-project.json
index 192de97..d35c93c 100644
--- a/.doctrine-project.json
+++ b/.doctrine-project.json
@@ -5,35 +5,34 @@
     "docsSlug": "doctrine-lexer",
     "versions": [
         {
-            "name": "3.0",
-            "branchName": "3.0.x",
+            "name": "3.1",
+            "branchName": "3.1.x",
             "slug": "latest",
             "upcoming": true
         },
+        {
+            "name": "3.0",
+            "branchName": "3.0.x",
+            "slug": "3.1",
+            "current": true
+        },
         {
             "name": "2.1",
             "branchName": "2.1.x",
-            "upcoming": true
+            "slug": "2.1",
+            "maintained": true
         },
         {
             "name": "2.0",
             "branchName": "2.0.x",
-            "aliases": [
-                "current",
-                "stable"
-            ]
-        },
-        {
-            "name": "1.3",
-            "branchName": "1.3.x",
-            "upcoming": true
+            "slug": "2.0",
+            "maintained": false
         },
         {
             "name": "1.2",
             "branchName": "1.2.x",
             "slug": "1.2",
-            "current": true,
-            "maintained": true
+            "maintained": false
         },
         {
             "name": "1.1",
diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml
index e64a966..1d7110a 100644
--- a/.github/workflows/coding-standards.yml
+++ b/.github/workflows/coding-standards.yml
@@ -24,4 +24,4 @@ on:
 jobs:
   coding-standards:
     name: "Coding Standards"
-    uses: "doctrine/.github/.github/workflows/coding-standards.yml@3.0.0"
+    uses: "doctrine/.github/.github/workflows/coding-standards.yml@4.0.0"
diff --git a/.github/workflows/composer-lint.yml b/.github/workflows/composer-lint.yml
index dbc934a..3707dcc 100644
--- a/.github/workflows/composer-lint.yml
+++ b/.github/workflows/composer-lint.yml
@@ -17,4 +17,4 @@ on:
 jobs:
   composer-lint:
     name: "Composer Lint"
-    uses: "doctrine/.github/.github/workflows/composer-lint.yml@3.0.0"
+    uses: "doctrine/.github/.github/workflows/composer-lint.yml@4.0.0"
diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index 17e894e..7982a44 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -24,6 +24,6 @@ on:
 jobs:
   phpunit:
     name: "PHPUnit"
-    uses: "doctrine/.github/.github/workflows/continuous-integration.yml@3.0.0"
+    uses: "doctrine/.github/.github/workflows/continuous-integration.yml@4.0.0"
     with:
-      php-versions: '["8.1", "8.2"]'
+      php-versions: '["8.1", "8.2", "8.3"]'
diff --git a/.github/workflows/release-on-milestone-closed.yml b/.github/workflows/release-on-milestone-closed.yml
index 949de82..34abfbc 100644
--- a/.github/workflows/release-on-milestone-closed.yml
+++ b/.github/workflows/release-on-milestone-closed.yml
@@ -8,7 +8,7 @@ on:
 jobs:
   release:
     name: "Git tag, release & create merge-up PR"
-    uses: "doctrine/.github/.github/workflows/release-on-milestone-closed.yml@2.1.0"
+    uses: "doctrine/.github/.github/workflows/release-on-milestone-closed.yml@4.0.0"
     secrets:
       GIT_AUTHOR_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }}
       GIT_AUTHOR_NAME: ${{ secrets.GIT_AUTHOR_NAME }}
diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
index b1cd768..c32da64 100644
--- a/.github/workflows/static-analysis.yml
+++ b/.github/workflows/static-analysis.yml
@@ -26,4 +26,4 @@ on:
 jobs:
   static-analysis:
     name: "Static Analysis"
-    uses: "doctrine/.github/.github/workflows/static-analysis.yml@3.0.0"
+    uses: "doctrine/.github/.github/workflows/static-analysis.yml@4.0.0"
diff --git a/composer.json b/composer.json
index 8a61afe..b6dd4e6 100644
--- a/composer.json
+++ b/composer.json
@@ -29,11 +29,11 @@
         "php": "^8.1"
     },
     "require-dev": {
-        "doctrine/coding-standard": "^10",
-        "phpstan/phpstan": "^1.9",
-        "phpunit/phpunit": "^9.5",
+        "doctrine/coding-standard": "^12",
+        "phpstan/phpstan": "^1.10",
+        "phpunit/phpunit": "^9.6",
         "psalm/plugin-phpunit": "^0.18.3",
-        "vimeo/psalm": "^5.0"
+        "vimeo/psalm": "^5.21"
     },
     "autoload": {
         "psr-4": {
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index b7b6083..86729bc 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -9,7 +9,7 @@
     <config name="php_version" value="80100"/>
 
     <!-- Ignore warnings and show progress of the run -->
-    <arg value="np"/>
+    <arg value="nps"/>
 
     <file>src</file>
     <file>tests</file>
diff --git a/psalm.xml b/psalm.xml
index fa14053..f335ebb 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -1,11 +1,13 @@
 <?xml version="1.0"?>
 <psalm
     errorLevel="1"
-    phpVersion="8.1"
+    phpVersion="8.3"
     resolveFromConfigFile="true"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns="https://getpsalm.org/schema/config"
     xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+    findUnusedBaselineEntry="true"
+    findUnusedCode="true"
 >
     <projectFiles>
         <directory name="src"/>
@@ -41,6 +43,12 @@
                 <file name="src/Token.php" />
             </errorLevel>
         </MixedReturnStatement>
+        <PossiblyUnusedProperty>
+            <errorLevel type="suppress">
+                <!-- TODO: Cover this property in a test -->
+                <referencedProperty name="Doctrine\Common\Lexer\Token::$position"/>
+            </errorLevel>
+        </PossiblyUnusedProperty>
         <ReferenceConstraintViolation>
             <errorLevel type="suppress">
                 <!-- https://github.com/vimeo/psalm/issues/8891 -->
diff --git a/src/AbstractLexer.php b/src/AbstractLexer.php
index 7c31935..2436885 100644
--- a/src/AbstractLexer.php
+++ b/src/AbstractLexer.php
@@ -49,21 +49,21 @@ abstract class AbstractLexer
     /**
      * The next token in the input.
      *
-     * @var mixed[]|null
-     * @psalm-var Token<T, V>|null
+     * @var Token<T, V>|null
      */
     public Token|null $lookahead;
 
     /**
      * The last matched/seen token.
      *
-     * @var mixed[]|null
-     * @psalm-var Token<T, V>|null
+     * @var Token<T, V>|null
      */
     public Token|null $token;
 
     /**
      * Composed regex for input parsing.
+     *
+     * @var non-empty-string|null
      */
     private string|null $regex = null;
 
@@ -203,8 +203,7 @@ public function isA(string $value, int|string|UnitEnum $token)
     /**
      * Moves the lookahead token forward.
      *
-     * @return mixed[]|null The next token or NULL if there are no more tokens ahead.
-     * @psalm-return Token<T, V>|null
+     * @return Token<T, V>|null The next token or NULL if there are no more tokens ahead.
      */
     public function peek()
     {
@@ -218,8 +217,7 @@ public function peek()
     /**
      * Peeks at the next token, returns it and immediately resets the peek.
      *
-     * @return mixed[]|null The next token or NULL if there are no more tokens ahead.
-     * @psalm-return Token<T, V>|null
+     * @return Token<T, V>|null The next token or NULL if there are no more tokens ahead.
      */
     public function glimpse()
     {
diff --git a/tests/AbstractLexerTest.php b/tests/AbstractLexerTest.php
index 4a74a9d..a441430 100644
--- a/tests/AbstractLexerTest.php
+++ b/tests/AbstractLexerTest.php
@@ -29,7 +29,7 @@ public function tearDown(): void
     }
 
     /** @psalm-return list<array{string, list<Token<string, string|int>>}> */
-    public function dataProvider(): array
+    public static function dataProvider(): array
     {
         return [
             [
@@ -170,7 +170,7 @@ public function testGlimpse(string $input, array $expectedTokens): void
     }
 
     /** @psalm-return list<array{string, int, string}> */
-    public function inputUntilPositionDataProvider(): array
+    public static function inputUntilPositionDataProvider(): array
     {
         return [
             ['price=10', 5, 'price'],