From 13eb3b02b87e23a4b546f1bca23d70d203b5e407 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=BDborn=C3=BD=20Adam?= <mail@adamvyborny.cz>
Date: Wed, 18 May 2022 15:06:38 +0200
Subject: [PATCH] Fix PHPStan and PHPCS

---
 composer.json                                 |   6 +-
 phpcs.xml                                     |   4 +
 phpstan-baseline.neon                         | 402 ----------
 phpstan.neon                                  |   2 -
 .../CsvMap/Exception/BadConfigException.php   |   3 +
 .../CsvMap/Exception/BadDataException.php     |   3 +
 .../CsvMap/Exception/CsvMapperException.php   |  21 +-
 src/Keboola/CsvMap/Mapper.php                 | 247 +++---
 .../CsvMap/MapperEmptyRelationTest.php        |  52 +-
 .../MapperNotAllowedPrimaryKeyValueTest.php   |  18 +-
 tests/Keboola/CsvMap/MapperShorthandTest.php  |  30 +-
 tests/Keboola/CsvMap/MapperTest.php           | 715 +++++++++++-------
 tests/Keboola/CsvMap/MapperWrongPathTest.php  |  52 +-
 13 files changed, 724 insertions(+), 831 deletions(-)
 create mode 100644 phpcs.xml
 delete mode 100644 phpstan-baseline.neon
 delete mode 100644 phpstan.neon

diff --git a/composer.json b/composer.json
index 0f71fc6..22ca4f8 100755
--- a/composer.json
+++ b/composer.json
@@ -23,9 +23,9 @@
         "phpunit/phpunit": ">=7.5"
     },
     "scripts": {
-        "phpstan": "phpstan analyse ./src ./tests --level=max --no-progress -c phpstan.neon",
-        "phpcs": "phpcs -n --ignore=vendor --extensions=php --standard=psr2 .",
-        "phpcbf": "phpcbf -n --ignore=vendor --extensions=php --standard=psr2 .",
+        "phpstan": "phpstan analyse ./src ./tests --level=8 --no-progress",
+        "phpcs": "phpcs -n --ignore=vendor --extensions=php .",
+        "phpcbf": "phpcbf -n --ignore=vendor --extensions=php .",
         "phplint": "parallel-lint -j 10 --exclude vendor .",
         "tests": "phpunit",
         "build": [
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 0000000..67e37cf
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<ruleset name="Project">
+    <rule ref="vendor/keboola/coding-standard/src/ruleset.xml"/>
+</ruleset>
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
deleted file mode 100644
index b8fd386..0000000
--- a/phpstan-baseline.neon
+++ /dev/null
@@ -1,402 +0,0 @@
-parameters:
-	ignoreErrors:
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Exception\\\\CsvMapperException\\:\\:getData\\(\\) return type has no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Exception/CsvMapperException.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Exception\\\\CsvMapperException\\:\\:setData\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Exception/CsvMapperException.php
-
-		-
-			message: "#^Property Keboola\\\\CsvMap\\\\Exception\\\\CsvMapperException\\:\\:\\$data has no type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Exception/CsvMapperException.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:__construct\\(\\) has parameter \\$mapping with no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:__construct\\(\\) has parameter \\$type with no type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:addParentPK\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:addParentPK\\(\\) has parameter \\$colName with no type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:checkPrimaryKeyValues\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:checkPrimaryKeyValues\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:expandShorthandDefinitions\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getHeader\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getParser\\(\\) has parameter \\$key with no type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getParser\\(\\) has parameter \\$settings with no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getParser\\(\\) should return static\\(Keboola\\\\CsvMap\\\\Mapper\\) but returns Keboola\\\\CsvMap\\\\Mapper\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getPrimaryKey\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getPrimaryKeyValues\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getPrimaryKeyValues\\(\\) has parameter \\$row with no type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getPrimaryKeyValues\\(\\) has parameter \\$userData with no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:getResultFile\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:mapRow\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:mapRow\\(\\) has parameter \\$row with no type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:mapRow\\(\\) has parameter \\$userData with no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:parse\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:parse\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:parse\\(\\) has parameter \\$userData with no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:parseRow\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:parseRow\\(\\) has parameter \\$userData with no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:setParentKey\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:setParentKey\\(\\) has parameter \\$colName with no type specified\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\Mapper\\:\\:setParentKey\\(\\) has parameter \\$keys with no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Property Keboola\\\\CsvMap\\\\Mapper\\:\\:\\$mapping type has no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Property Keboola\\\\CsvMap\\\\Mapper\\:\\:\\$parentKey type has no value type specified in iterable type array\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Property Keboola\\\\CsvMap\\\\Mapper\\:\\:\\$result \\(Keboola\\\\CsvTable\\\\Table\\) in empty\\(\\) is not falsy\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Unsafe usage of new static\\(\\)\\.$#"
-			count: 1
-			path: src/Keboola/CsvMap/Mapper.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperEmptyRelationTest\\:\\:getSampleDataMulti\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperEmptyRelationTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperEmptyRelationTest\\:\\:getSampleDataMultiFirstEmpty\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperEmptyRelationTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperEmptyRelationTest\\:\\:getSampleDataSimple\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperEmptyRelationTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperEmptyRelationTest\\:\\:testParseEmptyRelation\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperEmptyRelationTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperEmptyRelationTest\\:\\:testParseEmptyRelationFew\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperEmptyRelationTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperNotAllowedPrimaryKeyValueTest\\:\\:getSampleData\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperNotAllowedPrimaryKeyValueTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperNotAllowedPrimaryKeyValueTest\\:\\:testNotAllowedPrimaryKeyValue\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperNotAllowedPrimaryKeyValueTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperShorthandTest\\:\\:getSampleData\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperShorthandTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperShorthandTest\\:\\:testParseShorthand\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperShorthandTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperShorthandTest\\:\\:testParseShorthandWithRelation\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperShorthandTest.php
-
-		-
-			message: "#^Cannot access offset 0 on array\\<int, string\\>\\|false\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:getMixedData\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:getSampleData\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:getSampleDataSimple\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testArrayItemToColumn\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testArrayToString\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testArrayToTable\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testChildSameParser\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testDataInjection\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testDataInjectionNoData\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testDataInjectionPK\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testDeepNestedTable\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testDisableParentKey\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testDontWriteHeader\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testEmptyArray\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testEmptyString\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testMixedDataError\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testNoDestinationNestedTable\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testNoDestinationTable\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testNoMappingKeyColumn\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testNoTableMapping\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testObjectToColumnError\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testObjectToTable\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testParentKeyDestination\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testParentKeyPK\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testParse\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testParseCompositePK\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testParseNoPK\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testPrimaryKey\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testStringToArray\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperTest\\:\\:testUserDataPropagation\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperWrongPathTest\\:\\:getSampleDataMulti\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperWrongPathTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperWrongPathTest\\:\\:getSampleDataSimple\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperWrongPathTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperWrongPathTest\\:\\:testParseWrongBothMainAndRelation\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperWrongPathTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperWrongPathTest\\:\\:testParseWrongMain\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperWrongPathTest.php
-
-		-
-			message: "#^Method Keboola\\\\CsvMap\\\\MapperWrongPathTest\\:\\:testParseWrongRelation\\(\\) has no return type specified\\.$#"
-			count: 1
-			path: tests/Keboola/CsvMap/MapperWrongPathTest.php
-
diff --git a/phpstan.neon b/phpstan.neon
deleted file mode 100644
index 2ee6a55..0000000
--- a/phpstan.neon
+++ /dev/null
@@ -1,2 +0,0 @@
-includes:
-	- phpstan-baseline.neon
diff --git a/src/Keboola/CsvMap/Exception/BadConfigException.php b/src/Keboola/CsvMap/Exception/BadConfigException.php
index 7c72e49..200e08d 100644
--- a/src/Keboola/CsvMap/Exception/BadConfigException.php
+++ b/src/Keboola/CsvMap/Exception/BadConfigException.php
@@ -1,4 +1,7 @@
 <?php
+
+declare(strict_types=1);
+
 namespace Keboola\CsvMap\Exception;
 
 class BadConfigException extends CsvMapperException
diff --git a/src/Keboola/CsvMap/Exception/BadDataException.php b/src/Keboola/CsvMap/Exception/BadDataException.php
index 801f4dc..980c06d 100644
--- a/src/Keboola/CsvMap/Exception/BadDataException.php
+++ b/src/Keboola/CsvMap/Exception/BadDataException.php
@@ -1,4 +1,7 @@
 <?php
+
+declare(strict_types=1);
+
 namespace Keboola\CsvMap\Exception;
 
 class BadDataException extends CsvMapperException
diff --git a/src/Keboola/CsvMap/Exception/CsvMapperException.php b/src/Keboola/CsvMap/Exception/CsvMapperException.php
index 12fff34..6691586 100644
--- a/src/Keboola/CsvMap/Exception/CsvMapperException.php
+++ b/src/Keboola/CsvMap/Exception/CsvMapperException.php
@@ -1,24 +1,31 @@
 <?php
+
+declare(strict_types=1);
+
 namespace Keboola\CsvMap\Exception;
 
-class CsvMapperException extends \Exception
+use Exception;
+
+class CsvMapperException extends Exception
 {
 
-    protected $data = array();
+    /**
+     * @var array<mixed> $data
+     */
+    protected array $data = [];
 
     /**
-     * @return array
+     * @return array<mixed>
      */
-    public function getData()
+    public function getData(): array
     {
         return $this->data;
     }
 
     /**
-     * @param array $data
-     * @return $this
+     * @param array<mixed> $data
      */
-    public function setData(array $data)
+    public function setData(array $data): self
     {
         $this->data = $data;
 
diff --git a/src/Keboola/CsvMap/Mapper.php b/src/Keboola/CsvMap/Mapper.php
index bc3a0d1..2ffc8d3 100644
--- a/src/Keboola/CsvMap/Mapper.php
+++ b/src/Keboola/CsvMap/Mapper.php
@@ -1,51 +1,44 @@
 <?php
 
+declare(strict_types=1);
+
 namespace Keboola\CsvMap;
 
-use Keboola\CsvTable\Table;
 use Keboola\Csv\Exception as CsvException;
 use Keboola\CsvMap\Exception\BadConfigException;
 use Keboola\CsvMap\Exception\BadDataException;
+use Keboola\CsvTable\Table;
 use function Keboola\Utils\getDataFromPath;
 
-class Mapper
+final class Mapper
 {
     /**
-     * @var array
+     * @var array<string, array<string, mixed>|string>
      */
-    protected $mapping;
+    protected array $mapping;
 
-    /**
-     * @var bool
-     */
-    protected $writeHeader;
+    protected bool $writeHeader;
 
-    /**
-     * @var string
-     */
-    protected $type;
+    protected string $type;
 
-    /**
-     * @var Table
-     */
-    protected $result;
+    protected Table $result;
 
     /**
      * @var Mapper[]
      */
-    protected $parsers = [];
+    protected array $parsers = [];
 
     /**
-     * @var array
+     * @var array<string, string>
      */
-    protected $parentKey;
+    protected array $parentKey;
+
+    protected string $parentPK;
 
     /**
-     * @var string
+     * @param array<string, array<string, mixed>|string> $mapping
      */
-    protected $parentPK;
-
-    public function __construct(array $mapping, bool $writeHeader = true, $type = 'root')
+    public function __construct(array $mapping, bool $writeHeader = true, string $type = 'root')
     {
         $this->mapping = $mapping;
         $this->writeHeader = $writeHeader;
@@ -57,21 +50,29 @@ public function __construct(array $mapping, bool $writeHeader = true, $type = 'r
     /**
      * Expands shorthand definitions to theirs full definition
      */
-    private function expandShorthandDefinitions()
+    private function expandShorthandDefinitions(): void
     {
         foreach ($this->mapping as $key => $settings) {
             if (is_string($key) && is_string($settings)) {
                 $this->mapping[$key] = [
                     'type' => 'column',
                     'mapping' => [
-                        'destination' => $settings
-                    ]
+                        'destination' => $settings,
+                    ],
                 ];
             }
         }
     }
 
-    public function parse(array $data, array $userData = [])
+    /**
+     * @param array<int, array<string, mixed>|object> $data
+     * @param array<string, mixed> $userData
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\Utils\Exception
+     */
+    public function parse(array $data, array $userData = []): void
     {
         // Create a file, even if there is no data
         $this->getResultFile();
@@ -82,9 +83,13 @@ public function parse(array $data, array $userData = [])
     }
 
     /**
-     * @param object|mixed $row
+     * @param array<string, mixed> $userData
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\Utils\Exception
      */
-    public function parseRow($row, array $userData = [])
+    public function parseRow(mixed $row, array $userData = []): void
     {
         $file = $this->getResultFile();
         $mappedRow = $this->mapRow($row, $userData);
@@ -92,7 +97,7 @@ public function parseRow($row, array $userData = [])
         try {
             $file->writeRow($mappedRow);
         } catch (CsvException $e) {
-            if ($e->getCode() != 3) {
+            if ($e->getCode() !== 3) {
                 throw $e;
             }
 
@@ -104,71 +109,81 @@ public function parseRow($row, array $userData = [])
             }
             $badCols = join(',', array_keys($columns));
 
-            $exception = new BadDataException("Error writing '{$badCols}' column: " . $e->getMessage(), 0, $e);
+            $exception = new BadDataException("Error writing '$badCols' column: " . $e->getMessage(), 0, $e);
             $exception->setData(['bad_columns' => $columns]);
             throw $exception;
         }
     }
 
-    protected function mapRow($row, array $userData)
+    /**
+     * @param array<string, mixed> $userData
+     * @return array<int|string, mixed>
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\Utils\Exception
+     */
+    protected function mapRow(mixed $row, array $userData): array
     {
         $result = [];
         foreach ($this->mapping as $key => $settings) {
-            $delimiter = empty($settings['delimiter']) ? '.' : $settings['delimiter'];
+            $delimiter = empty($settings['delimiter']) ? '.' : (string) $settings['delimiter'];
             // Empty key means "self", ... it is useful to map scalar array values
             // Eg. row = {"actors":["Patrick Wilson","Rose Byrne","Barbara Hershey"]}
             //     mapping = {"actors: {"type": "table", "destination": "actor", "tableMapping": {"": "name:} }
-            $propertyValue = $key === '' && is_scalar($row) ? $row : getDataFromPath($key, $row, $delimiter);
+            $propertyValue = is_object($row) || is_array($row) ? getDataFromPath($key, $row, $delimiter) : $row;
 
-            if (empty($settings['type'])) {
-                $settings['type'] = 'column';
-            }
-            switch ($settings['type']) {
-                case 'table':
-                    $tableParser = $this->getParser($settings, $key);
+            if (is_array($settings)) {
+                if (empty($settings['type'])) {
+                    $settings['type'] = 'column';
+                }
+                switch ($settings['type']) {
+                    case 'table':
+                        $tableParser = $this->getParser($settings, $key);
+
+                        if (empty($this->getPrimaryKey()) && empty($propertyValue)) {
+                            if (empty($settings['parentKey']['disable'])) {
+                                $result[$settings['destination']] = null;
+                            }
+                            break;
+                        }
+
+                        $primaryKeyValue = $this->getPrimaryKeyValues($row, $userData);
+                        $this->checkPrimaryKeyValues($primaryKeyValue);
 
-                    if (empty($this->getPrimaryKey()) && empty($propertyValue)) {
                         if (empty($settings['parentKey']['disable'])) {
-                            $result[$settings['destination']] = null;
+                            if (empty($this->getPrimaryKey())) {
+                                $result[$settings['destination']] = join(',', $primaryKeyValue);
+                            }
+                            $parentKeyCol = empty($settings['parentKey']['destination'])
+                                ? $this->type . '_pk'
+                                : $settings['parentKey']['destination'];
+
+                            $tableParser->setParentKey($primaryKeyValue, $parentKeyCol);
+                            if (!empty($settings['parentKey']['primaryKey'])) {
+                                $tableParser->addParentPK($parentKeyCol);
+                            }
                         }
-                        break;
-                    }
 
-                    $primaryKeyValue = $this->getPrimaryKeyValues($row, $userData);
-                    $this->checkPrimaryKeyValues($primaryKeyValue);
-
-                    if (empty($settings['parentKey']['disable'])) {
-                        if (empty($this->getPrimaryKey())) {
-                            $result[$settings['destination']] = join(',', $primaryKeyValue);
+                        // If propertyValue != array, wrap it
+                        if (!is_array($propertyValue)) {
+                            $propertyValue = [$propertyValue];
                         }
-                        $parentKeyCol = empty($settings['parentKey']['destination'])
-                            ? $this->type . '_pk'
-                            : $settings['parentKey']['destination'];
+                        $tableParser->parse($propertyValue, $userData);
 
-                        $tableParser->setParentKey($primaryKeyValue, $parentKeyCol);
-                        if (!empty($settings['parentKey']['primaryKey'])) {
-                            $tableParser->addParentPK($parentKeyCol);
+                        break;
+                    case 'user':
+                        $result[$settings['mapping']['destination']] = getDataFromPath($key, $userData);
+                        break;
+                    case 'column':
+                    default:
+                        if (!is_scalar($propertyValue) && !is_null($propertyValue) && !empty($settings['forceType'])) {
+                            $propertyValue = json_encode($propertyValue);
                         }
-                    }
-
-                    // If propertyValue != array, wrap it
-                    if (!is_array($propertyValue)) {
-                        $propertyValue = [$propertyValue];
-                    }
-                    $tableParser->parse($propertyValue, $userData);
-
-                    break;
-                case 'user':
-                    $result[$settings['mapping']['destination']] = \Keboola\Utils\getDataFromPath($key, $userData);
-                    break;
-                case 'column':
-                default:
-                    if (!is_scalar($propertyValue) && !is_null($propertyValue) && !empty($settings['forceType'])) {
-                        $propertyValue = json_encode($propertyValue);
-                    }
-
-                    $result[$settings['mapping']['destination']] = $propertyValue;
-                    break;
+
+                        $result[$settings['mapping']['destination']] = $propertyValue;
+                        break;
+                }
             }
         }
         if (!empty($this->parentKey)) {
@@ -178,7 +193,11 @@ protected function mapRow($row, array $userData)
         return $result;
     }
 
-    private function checkPrimaryKeyValues(array $values)
+    /**
+     * @param array<int, mixed> $values
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    private function checkPrimaryKeyValues(array $values): void
     {
         foreach ($values as $value) {
             if (!is_scalar($value) && !is_null($value)) {
@@ -189,7 +208,10 @@ private function checkPrimaryKeyValues(array $values)
         }
     }
 
-    public function getPrimaryKey()
+    /**
+     * @return array<string, mixed>
+     */
+    public function getPrimaryKey(): array
     {
         $primaryKey = [];
         foreach ($this->mapping as $path => $settings) {
@@ -204,7 +226,12 @@ public function getPrimaryKey()
         return $primaryKey;
     }
 
-    protected function getPrimaryKeyValues($row, array $userData)
+    /**
+     * @param array<string, mixed> $userData
+     * @return array<int, mixed>
+     * @throws \Keboola\Utils\Exception
+     */
+    protected function getPrimaryKeyValues(mixed $row, array $userData): array
     {
         $values = [];
         if (empty($this->getPrimaryKey())) {
@@ -215,13 +242,13 @@ protected function getPrimaryKeyValues($row, array $userData)
             }
         } else {
             foreach ($this->getPrimaryKey() as $path => $column) {
-                if (!empty($this->parentKey) && $column == key($this->parentKey)) {
+                if (!empty($this->parentKey) && $column === key($this->parentKey)) {
                     $values[] = $this->parentKey[$column];
-                } elseif (!empty($this->mapping[$path]['type']) && $this->mapping[$path]['type'] == 'user') {
+                } elseif (!empty($this->mapping[$path]['type']) && $this->mapping[$path]['type'] === 'user') {
                     $values[] = $userData[$path];
                 } else {
                     $delimiter = empty($this->mapping[$path]['delimiter']) ? '.' : $this->mapping[$path]['delimiter'];
-                    $values[] = \Keboola\Utils\getDataFromPath($path, $row, $delimiter);
+                    $values[] = getDataFromPath($path, $row, $delimiter);
                 }
             }
         }
@@ -229,7 +256,10 @@ protected function getPrimaryKeyValues($row, array $userData)
         return $values;
     }
 
-    public function setParentKey(array $keys, $colName)
+    /**
+     * @param array<int, string> $keys
+     */
+    public function setParentKey(array $keys, string $colName): void
     {
         $this->parentKey = [$colName => join(',', $keys)];
     }
@@ -237,17 +267,18 @@ public function setParentKey(array $keys, $colName)
     /**
      * Add parent identifier to PK
      */
-    public function addParentPK($colName)
+    public function addParentPK(string $colName): void
     {
         $this->parentPK = $colName;
     }
 
     /**
-     * @return static
+     * @param array<string, string|mixed> $settings
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
      */
-    protected function getParser(array $settings, $key)
+    protected function getParser(array $settings, string $key): Mapper
     {
-        if (!empty($settings['destination']) && $settings['destination'] == $this->type) {
+        if (!empty($settings['destination']) && $settings['destination'] === $this->type) {
             if (empty($settings['parentKey']['disable'])) {
                 throw new BadConfigException(
                     "'parentKey.disable' must be true to parse child values into parent's table"
@@ -259,18 +290,23 @@ protected function getParser(array $settings, $key)
 
         foreach (['tableMapping', 'destination'] as $requiredKey) {
             if (empty($settings[$requiredKey])) {
-                throw new BadConfigException("Key '{$requiredKey}' is not set for table '{$key}'.");
+                throw new BadConfigException("Key '$requiredKey' is not set for table '$key'.");
             }
         }
 
         if (empty($this->parsers[$settings['destination']])) {
             $this->parsers[$settings['destination']] =
-                new static($settings['tableMapping'], $this->writeHeader, $settings['destination']);
+                new self($settings['tableMapping'], $this->writeHeader, $settings['destination']);
         }
         return $this->parsers[$settings['destination']];
     }
 
-    protected function getResultFile()
+    /**
+     * @throws \Keboola\Csv\InvalidArgumentException
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    protected function getResultFile(): Table
     {
         if (empty($this->result)) {
             $this->result = new Table($this->type, $this->getHeader(), $this->writeHeader);
@@ -280,23 +316,27 @@ protected function getResultFile()
         return $this->result;
     }
 
-    protected function getHeader()
+    /**
+     * @return array<int, mixed>
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    protected function getHeader(): array
     {
         $header = [];
         foreach ($this->mapping as $key => $settings) {
             if (empty($settings['type'])
-                || $settings['type'] == 'column'
-                || $settings['type'] == 'user'
+                || $settings['type'] === 'column'
+                || $settings['type'] === 'user'
             ) {
                 if (empty($settings['mapping']['destination'])) {
-                    throw new BadConfigException("Key 'mapping.destination' is not set for column '{$key}'.");
+                    throw new BadConfigException("Key 'mapping.destination' is not set for column '$key'.");
                 }
 
                 $header[] = $settings['mapping']['destination'];
-            } elseif ($settings['type'] == 'table' && empty($this->getPrimaryKey())) {
+            } elseif ($settings['type'] === 'table' && empty($this->getPrimaryKey())) {
                 // TODO child table link to generate
                 if (empty($settings['destination'])) {
-                    throw new BadConfigException("Key 'destination' is not set for table '{$key}'.");
+                    throw new BadConfigException("Key 'destination' is not set for table '$key'.");
                 }
 
                 if (empty($settings['parentKey']['disable'])) {
@@ -312,22 +352,23 @@ protected function getHeader()
 
     /**
      * Return own result and all children
-     * @return Table[]
+     * @return array<string, Table>
+     * @throws \Keboola\Csv\InvalidArgumentException
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
      */
-    public function getCsvFiles()
+    public function getCsvFiles(): array
     {
         $childResults = [];
-        foreach ($this->parsers as $type => $parser) {
+        foreach ($this->parsers as $parser) {
             $childResults += $parser->getCsvFiles();
         }
 
-        $results = array_merge(
+        return array_merge(
             [
-                $this->type => $this->result
+                $this->type => $this->getResultFile(),
             ],
             $childResults
         );
-
-        return $results;
     }
 }
diff --git a/tests/Keboola/CsvMap/MapperEmptyRelationTest.php b/tests/Keboola/CsvMap/MapperEmptyRelationTest.php
index 9cc7e98..11b6dd3 100644
--- a/tests/Keboola/CsvMap/MapperEmptyRelationTest.php
+++ b/tests/Keboola/CsvMap/MapperEmptyRelationTest.php
@@ -1,12 +1,20 @@
 <?php
 
+declare(strict_types=1);
+
 namespace Keboola\CsvMap;
 
 use PHPUnit\Framework\TestCase;
 
 class MapperEmptyRelationTest extends TestCase
 {
-    public function testParseEmptyRelation()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testParseEmptyRelation(): void
     {
         $mapping = [
             'id' => [
@@ -14,7 +22,7 @@ public function testParseEmptyRelation()
                 'mapping' => [
                     'destination' => 'pk',
                     'primaryKey' => true,
-                ]
+                ],
             ],
             'timestamp' => 'timestamp',
             'reactions' => [
@@ -23,8 +31,8 @@ public function testParseEmptyRelation()
                 'tableMapping' => [
                     'user.id' => 'id',
                     'user.username' => 'username',
-                ]
-            ]
+                ],
+            ],
         ];
 
         // one row
@@ -41,7 +49,6 @@ public function testParseEmptyRelation()
         $this->assertFileExists($file1->getPathname());
         $this->assertEquals($expected1, file_get_contents($file1->getPathname()));
 
-
         $file2 = $parser->getCsvFiles()['reactions'];
 
         $expected2 = <<<CSV
@@ -65,17 +72,19 @@ public function testParseEmptyRelation()
         $this->assertFileExists($file1->getPathname());
         $this->assertEquals($expected1, file_get_contents($file1->getPathname()));
 
-
         $file2 = $parser->getCsvFiles()['reactions'];
 
-        $expected2 = <<<CSV
-"id","username","root_pk"\n
-CSV;
         $this->assertFileExists($file2->getPathname());
         $this->assertEquals($expected2, file_get_contents($file2->getPathname()));
     }
 
-    public function testParseEmptyRelationFew()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    public function testParseEmptyRelationFew(): void
     {
         $mapping = [
             'id' => [
@@ -83,7 +92,7 @@ public function testParseEmptyRelationFew()
                 'mapping' => [
                     'destination' => 'pk',
                     'primaryKey' => true,
-                ]
+                ],
             ],
             'timestamp' => 'timestamp',
             'reactions' => [
@@ -92,8 +101,8 @@ public function testParseEmptyRelationFew()
                 'tableMapping' => [
                     'user.id' => 'id',
                     'user.username' => 'username',
-                ]
-            ]
+                ],
+            ],
         ];
 
         // multiple rows
@@ -113,7 +122,6 @@ public function testParseEmptyRelationFew()
         $this->assertFileExists($file1->getPathname());
         $this->assertEquals($expected1, file_get_contents($file1->getPathname()));
 
-
         $file2 = $parser->getCsvFiles()['reactions'];
 
         $expected2 = <<<CSV
@@ -125,7 +133,10 @@ public function testParseEmptyRelationFew()
         $this->assertEquals($expected2, file_get_contents($file2->getPathname()));
     }
 
-    protected function getSampleDataSimple()
+    /**
+     * @return array<int, array<string, mixed>>
+     */
+    protected function getSampleDataSimple(): array
     {
         $json = <<<JSON
 [
@@ -139,7 +150,10 @@ protected function getSampleDataSimple()
         return json_decode($json, true);
     }
 
-    protected function getSampleDataMulti()
+    /**
+     * @return array<int, array<string, mixed>>
+     */
+    protected function getSampleDataMulti(): array
     {
         $json = <<<JSON
 [
@@ -158,8 +172,10 @@ protected function getSampleDataMulti()
         return json_decode($json, true);
     }
 
-
-    protected function getSampleDataMultiFirstEmpty()
+    /**
+     * @return array<int, array<string, mixed>>
+     */
+    protected function getSampleDataMultiFirstEmpty(): array
     {
         $json = <<<JSON
 [
diff --git a/tests/Keboola/CsvMap/MapperNotAllowedPrimaryKeyValueTest.php b/tests/Keboola/CsvMap/MapperNotAllowedPrimaryKeyValueTest.php
index ba0ceae..fb6a549 100644
--- a/tests/Keboola/CsvMap/MapperNotAllowedPrimaryKeyValueTest.php
+++ b/tests/Keboola/CsvMap/MapperNotAllowedPrimaryKeyValueTest.php
@@ -1,5 +1,7 @@
 <?php
 
+declare(strict_types=1);
+
 namespace Keboola\CsvMap;
 
 use Keboola\CsvMap\Exception\BadConfigException;
@@ -9,8 +11,11 @@ class MapperNotAllowedPrimaryKeyValueTest extends TestCase
 {
     /**
      * Primary key: [{"$oid":"5716054bee6e764c94fa85a6"}]
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Csv\Exception
      */
-    public function testNotAllowedPrimaryKeyValue()
+    public function testNotAllowedPrimaryKeyValue(): void
     {
         $config = [
             '_id' => [
@@ -18,15 +23,15 @@ public function testNotAllowedPrimaryKeyValue()
                 'mapping' => [
                     'destination' => 'id',
                     'primaryKey' => true,
-                ]
+                ],
             ],
             'coord' => [
                 'type' => 'table',
                 'destination' => 'coord',
                 'tableMapping' => [
                     'a' => 'a',
-                ]
-            ]
+                ],
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -37,7 +42,10 @@ public function testNotAllowedPrimaryKeyValue()
         $parser->parse($data);
     }
 
-    protected function getSampleData()
+    /**
+     * @return array<int, object>
+     */
+    protected function getSampleData(): array
     {
         $json = <<<JSON
 [
diff --git a/tests/Keboola/CsvMap/MapperShorthandTest.php b/tests/Keboola/CsvMap/MapperShorthandTest.php
index 5963fa6..0eeda47 100644
--- a/tests/Keboola/CsvMap/MapperShorthandTest.php
+++ b/tests/Keboola/CsvMap/MapperShorthandTest.php
@@ -1,5 +1,7 @@
 <?php
 
+declare(strict_types=1);
+
 namespace Keboola\CsvMap;
 
 use PHPUnit\Framework\TestCase;
@@ -7,7 +9,13 @@
 class MapperShorthandTest extends TestCase
 {
 
-    public function testParseShorthand()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    public function testParseShorthand(): void
     {
         $config = [
             'id' => 'id',
@@ -27,7 +35,13 @@ public function testParseShorthand()
         $this->assertEquals($expected, file_get_contents($file->getPathname()));
     }
 
-    public function testParseShorthandWithRelation()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testParseShorthandWithRelation(): void
     {
         $config = [
             'id' => [
@@ -35,7 +49,7 @@ public function testParseShorthandWithRelation()
                 'mapping' => [
                     'destination' => 'pk',
                     'primaryKey' => true,
-                ]
+                ],
             ],
             'timestamp' => 'timestamp',
             'reactions' => [
@@ -44,8 +58,8 @@ public function testParseShorthandWithRelation()
                 'tableMapping' => [
                     'user.id' => 'id',
                     'user.username' => 'username',
-                ]
-            ]
+                ],
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -60,7 +74,6 @@ public function testParseShorthandWithRelation()
 CSV;
         $this->assertEquals($expected1, file_get_contents($file1->getPathname()));
 
-
         $file2 = $parser->getCsvFiles()['reactions'];
 
         $expected2 = <<<CSV
@@ -71,7 +84,10 @@ public function testParseShorthandWithRelation()
         $this->assertEquals($expected2, file_get_contents($file2->getPathname()));
     }
 
-    protected function getSampleData()
+    /**
+     * @return array<int, array<string, mixed>>
+     */
+    protected function getSampleData(): array
     {
         $json = <<<JSON
 [
diff --git a/tests/Keboola/CsvMap/MapperTest.php b/tests/Keboola/CsvMap/MapperTest.php
index 978cbfa..bd4fb84 100644
--- a/tests/Keboola/CsvMap/MapperTest.php
+++ b/tests/Keboola/CsvMap/MapperTest.php
@@ -1,5 +1,7 @@
 <?php
 
+declare(strict_types=1);
+
 namespace Keboola\CsvMap;
 
 use Keboola\CsvMap\Exception\BadConfigException;
@@ -8,27 +10,33 @@
 
 class MapperTest extends TestCase
 {
-    public function testParse()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    public function testParse(): void
     {
         $config = [
             'timestamp' => [
                 'type' => 'column',
                 'mapping' => [
-                    'destination' => 'timestamp'
-                ]
+                    'destination' => 'timestamp',
+                ],
             ],
             'id' => [
                 'type' => 'column',
                 'mapping' => [
                     'destination' => 'post_id',
-                    'primaryKey' => true
-                ]
+                    'primaryKey' => true,
+                ],
             ],
             'user.id' => [
                 'type' => 'column',
                 'mapping' => [
-                    'destination' => 'user_id'
-                ]
+                    'destination' => 'user_id',
+                ],
             ],
             'reactions' => [
                 'type' => 'table',
@@ -37,17 +45,17 @@ public function testParse()
                     'user/id' => [
                         'type' => 'column',
                         'mapping' => [
-                            'destination' => 'user_id'
+                            'destination' => 'user_id',
                         ],
-                        'delimiter' => '/'
-                    ]
+                        'delimiter' => '/',
+                    ],
                 ],
 //                 'parentKey' => [
 //                     'primaryKey' => true,
 //                     //'columns' => ['id', 'user_id'],
 //                     //'hash' => true
 //                 ]
-            ]
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -62,26 +70,32 @@ public function testParse()
         }
     }
 
-    public function testParseNoPK()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testParseNoPK(): void
     {
         $config = [
             'timestamp' => [
                 'type' => 'column',
                 'mapping' => [
-                    'destination' => 'timestamp'
-                ]
+                    'destination' => 'timestamp',
+                ],
             ],
             'id' => [
                 'type' => 'column',
                 'mapping' => [
-                    'destination' => 'post_id'
-                ]
+                    'destination' => 'post_id',
+                ],
             ],
             'user.id' => [
                 'type' => 'column',
                 'mapping' => [
-                    'destination' => 'user_id'
-                ]
+                    'destination' => 'user_id',
+                ],
             ],
             'reactions' => [
                 'type' => 'table',
@@ -90,11 +104,11 @@ public function testParseNoPK()
                     'user.id' => [
                         'type' => 'column',
                         'mapping' => [
-                            'destination' => 'user_id'
-                        ]
-                    ]
-                ]
-            ]
+                            'destination' => 'user_id',
+                        ],
+                    ],
+                ],
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -109,28 +123,34 @@ public function testParseNoPK()
         }
     }
 
-    public function testParseCompositePK()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testParseCompositePK(): void
     {
         $config = [
             'timestamp' => [
                 'type' => 'column',
                 'mapping' => [
-                    'destination' => 'timestamp'
-                ]
+                    'destination' => 'timestamp',
+                ],
             ],
             'id' => [
                 'type' => 'column',
                 'mapping' => [
                     'destination' => 'post_id',
-                    'primaryKey' => true
-                ]
+                    'primaryKey' => true,
+                ],
             ],
             'user.id' => [
                 'type' => 'column',
                 'mapping' => [
                     'destination' => 'user_id',
-                    'primaryKey' => true
-                ]
+                    'primaryKey' => true,
+                ],
             ],
             'reactions' => [
                 'type' => 'table',
@@ -139,11 +159,11 @@ public function testParseCompositePK()
                     'user.id' => [
                         'type' => 'column',
                         'mapping' => [
-                            'destination' => 'user_id'
-                        ]
-                    ]
-                ]
-            ]
+                            'destination' => 'user_id',
+                        ],
+                    ],
+                ],
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -157,15 +177,21 @@ public function testParseCompositePK()
         }
     }
 
-    public function testParentKeyPK()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testParentKeyPK(): void
     {
         $config = [
             'id' => [
                 'type' => 'column',
                 'mapping' => [
                     'destination' => 'post_id',
-                    'primaryKey' => true
-                ]
+                    'primaryKey' => true,
+                ],
             ],
             'reactions' => [
                 'type' => 'table',
@@ -175,14 +201,14 @@ public function testParentKeyPK()
                         'type' => 'column',
                         'mapping' => [
                             'destination' => 'user_id',
-                            'primaryKey' => true
-                        ]
-                    ]
+                            'primaryKey' => true,
+                        ],
+                    ],
                 ],
                 'parentKey' => [
-                    'primaryKey' => true
-                ]
-            ]
+                    'primaryKey' => true,
+                ],
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -194,15 +220,21 @@ public function testParentKeyPK()
         $this->assertEquals(['user_id', 'root_pk'], $result['post_reactions']->getPrimaryKey(true));
     }
 
-    public function testParentKeyDestination()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testParentKeyDestination(): void
     {
         $config = [
             'id' => [
                 'type' => 'column',
                 'mapping' => [
                     'destination' => 'post_id',
-                    'primaryKey' => true
-                ]
+                    'primaryKey' => true,
+                ],
             ],
             'reactions' => [
                 'type' => 'table',
@@ -212,14 +244,14 @@ public function testParentKeyDestination()
                         'type' => 'column',
                         'mapping' => [
                             'destination' => 'user_id',
-                            'primaryKey' => true
-                        ]
-                    ]
+                            'primaryKey' => true,
+                        ],
+                    ],
                 ],
                 'parentKey' => [
-                    'destination' => 'post_id'
-                ]
-            ]
+                    'destination' => 'post_id',
+                ],
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -228,16 +260,26 @@ public function testParentKeyDestination()
         $parser->parse($data);
         $result = $parser->getCsvFiles();
 
-        $this->assertEquals('"user_id","post_id"' . PHP_EOL, file($result['post_reactions']->getPathName())[0]);
+        $file = file($result['post_reactions']->getPathName());
+        if ($file === false) {
+            $this->fail();
+        }
+        $this->assertEquals('"user_id","post_id"' . PHP_EOL, $file[0]);
     }
 
-    public function testEmptyArray()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    public function testEmptyArray(): void
     {
         $config = [
             'id' => [
                 'mapping' => [
-                    'destination' => 'id'
-                ]
+                    'destination' => 'id',
+                ],
             ],
             'arr' => [
                 'type' => 'table',
@@ -245,17 +287,17 @@ public function testEmptyArray()
                 'tableMapping' => [
                     'child_id' => [
                         'mapping' => [
-                            'destination' => 'child_id'
-                        ]
-                    ]
-                ]
-            ]
+                            'destination' => 'child_id',
+                        ],
+                    ],
+                ],
+            ],
         ];
 
         $data = [
-            (object)[
-                'id' => 1
-            ]
+            (object) [
+                'id' => 1,
+            ],
         ];
 
         $parser = new Mapper($config);
@@ -265,29 +307,35 @@ public function testEmptyArray()
         $this->assertEquals(['"id","children"' . PHP_EOL, '"1",""' . PHP_EOL], file($result['root']->getPathName()));
     }
 
-    public function testEmptyString()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    public function testEmptyString(): void
     {
         $config = [
             'id' => [
                 'mapping' => [
-                    'destination' => 'id'
-                ]
+                    'destination' => 'id',
+                ],
             ],
             'str' => [
                 'mapping' => [
-                    'destination' => 'text'
-                ]
-            ]
+                    'destination' => 'text',
+                ],
+            ],
         ];
 
         $data = [
-            (object)[
+            (object) [
                 'id' => 1,
-                'str' => 'asdf'
+                'str' => 'asdf',
+            ],
+            (object) [
+                'id' => 2,
             ],
-            (object)[
-                'id' => 2
-            ]
         ];
 
         $parser = new Mapper($config);
@@ -298,34 +346,40 @@ public function testEmptyString()
             [
                 '"id","text"' . PHP_EOL,
                 '"1","asdf"' . PHP_EOL,
-                '"2",""' . PHP_EOL
+                '"2",""' . PHP_EOL,
             ],
             file($result['root']->getPathName())
         );
     }
 
-    public function testPrimaryKey()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testPrimaryKey(): void
     {
         $config = [
             'timestamp' => [
                 'type' => 'column',
                 'mapping' => [
-                    'destination' => 'timestamp'
-                ]
+                    'destination' => 'timestamp',
+                ],
             ],
             'id' => [
                 'type' => 'column',
                 'mapping' => [
                     'destination' => 'post_id',
-                    'primaryKey' => true
-                ]
+                    'primaryKey' => true,
+                ],
             ],
             'user.id' => [
                 'type' => 'column',
                 'mapping' => [
-                    'destination' => 'user_id'
-                ]
-            ]
+                    'destination' => 'user_id',
+                ],
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -337,13 +391,18 @@ public function testPrimaryKey()
         $this->assertEquals(['post_id'], $result['root']->getPrimaryKey(true));
     }
 
-    public function testNoMappingKeyColumn()
+    /**
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testNoMappingKeyColumn(): void
     {
 
         $config = [
             'timestamp' => [
-                'type' => 'column'
-            ]
+                'type' => 'column',
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -355,13 +414,18 @@ public function testNoMappingKeyColumn()
         $parser->parse($data);
     }
 
-    public function testNoDestinationTable()
+    /**
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testNoDestinationTable(): void
     {
 
         $config = [
             'arr' => [
-                'type' => 'table'
-            ]
+                'type' => 'table',
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -372,13 +436,18 @@ public function testNoDestinationTable()
         $parser->parse($data);
     }
 
-    public function testNoTableMapping()
+    /**
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testNoTableMapping(): void
     {
         $config = [
             'reactions' => [
                 'type' => 'table',
-                'destination' => 'children'
-            ]
+                'destination' => 'children',
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -389,7 +458,12 @@ public function testNoTableMapping()
         $parser->parse($data);
     }
 
-    public function testNoDestinationNestedTable()
+    /**
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testNoDestinationNestedTable(): void
     {
         $config = [
             'reactions' => [
@@ -397,11 +471,11 @@ public function testNoDestinationNestedTable()
                 'tableMapping' => [
                     'child_id' => [
                         'mapping' => [
-                            'destination' => 'child_id'
-                        ]
-                    ]
-                ]
-            ]
+                            'destination' => 'child_id',
+                        ],
+                    ],
+                ],
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -412,20 +486,26 @@ public function testNoDestinationNestedTable()
         $parser->parse($data);
     }
 
-    public function testDataInjection()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testDataInjection(): void
     {
         $config = [
             'id' => [
                 'mapping' => [
-                    'destination' => 'id'
-                ]
+                    'destination' => 'id',
+                ],
             ],
             'userData' => [
                 'type' => 'user',
                 'mapping' => [
-                    'destination' => 'userCol'
-                ]
-            ]
+                    'destination' => 'userCol',
+                ],
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -437,20 +517,26 @@ public function testDataInjection()
         $this->assertEquals(
             [
                 '"id","userCol"' . PHP_EOL,
-                '"1","blah"' . PHP_EOL
+                '"1","blah"' . PHP_EOL,
             ],
             file($result['root']->getPathName())
         );
     }
 
-    public function testDataInjectionPK()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testDataInjectionPK(): void
     {
         $config = [
             'id' => [
                 'mapping' => [
                     'destination' => 'id',
-                    'primaryKey' => true
-                ]
+                    'primaryKey' => true,
+                ],
             ],
             'reactions' => [
                 'type' => 'table',
@@ -459,18 +545,18 @@ public function testDataInjectionPK()
                     'user.id' => [
                         'type' => 'column',
                         'mapping' => [
-                            'destination' => 'user_id'
-                        ]
-                    ]
-                ]
+                            'destination' => 'user_id',
+                        ],
+                    ],
+                ],
             ],
             'userData' => [
                 'type' => 'user',
                 'mapping' => [
                     'destination' => 'userCol',
-                    'primaryKey' => true
-                ]
-            ]
+                    'primaryKey' => true,
+                ],
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -482,7 +568,7 @@ public function testDataInjectionPK()
         $this->assertEquals(
             [
                 '"id","userCol"' . PHP_EOL,
-                '"1","blah"' . PHP_EOL
+                '"1","blah"' . PHP_EOL,
             ],
             file($result['root']->getPathName())
         );
@@ -492,26 +578,32 @@ public function testDataInjectionPK()
             [
                 '"user_id","root_pk"' . PHP_EOL,
                 '"456","1,blah"' . PHP_EOL,
-                '"789","1,blah"' . PHP_EOL
+                '"789","1,blah"' . PHP_EOL,
             ],
             file($result['post_reactions']->getPathName())
         );
     }
 
-    public function testDataInjectionNoData()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    public function testDataInjectionNoData(): void
     {
         $config = [
             'id' => [
                 'mapping' => [
-                    'destination' => 'id'
-                ]
+                    'destination' => 'id',
+                ],
             ],
             'userData' => [
                 'type' => 'user',
                 'mapping' => [
-                    'destination' => 'userCol'
-                ]
-            ]
+                    'destination' => 'userCol',
+                ],
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -523,21 +615,27 @@ public function testDataInjectionNoData()
         $this->assertEquals(
             [
                 '"id","userCol"' . PHP_EOL,
-                '"1",""' . PHP_EOL
+                '"1",""' . PHP_EOL,
             ],
             file($result['root']->getPathName())
         );
     }
 
-    public function testUserDataPropagation()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testUserDataPropagation(): void
     {
         $data = $this->getSampleData();
 
         $config = [
             'id' => [
                 'mapping' => [
-                    'destination' => 'id'
-                ]
+                    'destination' => 'id',
+                ],
             ],
             'user' => [
                 'type' => 'table',
@@ -546,36 +644,36 @@ public function testUserDataPropagation()
                     'id' => [
                         'mapping' => [
                             'destination' => 'id',
-                            'primaryKey' => true
-                        ]
+                            'primaryKey' => true,
+                        ],
                     ],
                     'username' => [
                         'mapping' => [
-                            'destination' => 'username'
-                        ]
+                            'destination' => 'username',
+                        ],
                     ],
                     'keboola_source' => [
                         'type' => 'user',
                         'mapping' => [
-                            'destination' => 'keboola_source'
-                        ]
-                    ]
+                            'destination' => 'keboola_source',
+                        ],
+                    ],
                 ],
                 'parentKey' => [
-                    'disable' => true
-                ]
+                    'disable' => true,
+                ],
             ],
             'user.id' => [
                 'mapping' => [
-                    'destination' => 'user_id'
-                ]
+                    'destination' => 'user_id',
+                ],
             ],
             'keboola_source' => [
                 'type' => 'user',
                 'mapping' => [
-                    'destination' => 'keboola_source'
-                ]
-            ]
+                    'destination' => 'keboola_source',
+                ],
+            ],
         ];
 
         $parser = new Mapper($config);
@@ -586,23 +684,29 @@ public function testUserDataPropagation()
 
         $this->assertEquals([
             '"id","user_id","keboola_source"' . PHP_EOL,
-            '"1","123","search"' . PHP_EOL
+            '"1","123","search"' . PHP_EOL,
         ], file($result['root']->getPathName()));
         $this->assertEquals([
             '"id","username","keboola_source"' . PHP_EOL,
-            '"123","alois","search"' . PHP_EOL
+            '"123","alois","search"' . PHP_EOL,
         ], file($result['users']->getPathName()));
     }
 
-    public function testObjectToTable()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    public function testObjectToTable(): void
     {
         $data = $this->getSampleData();
 
         $config = [
             'id' => [
                 'mapping' => [
-                    'destination' => 'id'
-                ]
+                    'destination' => 'id',
+                ],
             ],
             'user' => [
                 'type' => 'table',
@@ -611,24 +715,24 @@ public function testObjectToTable()
                     'id' => [
                         'mapping' => [
                             'destination' => 'id',
-                            'primaryKey' => true
-                        ]
+                            'primaryKey' => true,
+                        ],
                     ],
                     'username' => [
                         'mapping' => [
-                            'destination' => 'username'
-                        ]
-                    ]
+                            'destination' => 'username',
+                        ],
+                    ],
                 ],
                 'parentKey' => [
-                    'disable' => true
-                ]
+                    'disable' => true,
+                ],
             ],
             'user.id' => [
                 'mapping' => [
-                    'destination' => 'user_id'
-                ]
-            ]
+                    'destination' => 'user_id',
+                ],
+            ],
         ];
 
         $parser = new Mapper($config);
@@ -645,15 +749,21 @@ public function testObjectToTable()
         );
     }
 
-    public function testDisableParentKey()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testDisableParentKey(): void
     {
 
         $config = [
             'id' => [
                 'type' => 'column',
                 'mapping' => [
-                    'destination' => 'post_id'
-                ]
+                    'destination' => 'post_id',
+                ],
             ],
             'reactions' => [
                 'type' => 'table',
@@ -662,14 +772,14 @@ public function testDisableParentKey()
                     'user.id' => [
                         'type' => 'column',
                         'mapping' => [
-                            'destination' => 'user_id'
-                        ]
-                    ]
+                            'destination' => 'user_id',
+                        ],
+                    ],
                 ],
                 'parentKey' => [
-                    'disable' => true
-                ]
-            ]
+                    'disable' => true,
+                ],
+            ],
         ];
 
         $data = $this->getSampleData();
@@ -680,48 +790,54 @@ public function testDisableParentKey()
 
         $this->assertEquals([
             '"post_id"' . PHP_EOL,
-            '"1"' . PHP_EOL
+            '"1"' . PHP_EOL,
         ], file($result['root']->getPathName()));
         $this->assertEquals([
             '"user_id"' . PHP_EOL, '"456"' . PHP_EOL,
-            '"789"' . PHP_EOL
+            '"789"' . PHP_EOL,
         ], file($result['post_reactions']->getPathName()));
     }
 
-    public function testChildSameParser()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    public function testChildSameParser(): void
     {
         $data = [
-            (object)[
+            (object) [
                 'id' => 1,
-                'child' => (object)[
-                    'id' => 1.1
+                'child' => (object) [
+                    'id' => 1.1,
                 ],
                 'arrChild' => [ // redundant?
-                    (object)['id' => '1.2']
-                ]
-            ]
+                    (object) ['id' => '1.2'],
+                ],
+            ],
         ];
 
         $config = [
             'id' => [
                 'mapping' => [
-                    'destination' => 'post_id'
-                ]
+                    'destination' => 'post_id',
+                ],
             ],
             'child' => [
                 'type' => 'table',
                 'destination' => 'items',
                 'parentKey' => [
-                    'disable' => true
-                ]
+                    'disable' => true,
+                ],
             ],
             'arrChild' => [
                 'type' => 'table',
                 'destination' => 'items',
                 'parentKey' => [
-                    'disable' => true
-                ]
-            ]
+                    'disable' => true,
+                ],
+            ],
         ];
 
         $parser = new Mapper($config, true, 'items');
@@ -732,26 +848,32 @@ public function testChildSameParser()
             '"post_id"' . PHP_EOL,
             '"1.1"' . PHP_EOL,
             '"1.2"' . PHP_EOL,
-            '"1"' . PHP_EOL
+            '"1"' . PHP_EOL,
         ], file($result['items']->getPathName()));
     }
 
-    public function testArrayItemToColumn()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    public function testArrayItemToColumn(): void
     {
         $config = [
             'arr.0' => [
                 'mapping' => [
-                    'destination' => 'first_arr_item'
-                ]
-            ]
+                    'destination' => 'first_arr_item',
+                ],
+            ],
         ];
 
         $data = [
-            (object)[
+            (object) [
                 'arr' => [
-                    'one', 'two'
-                ]
-            ]
+                    'one', 'two',
+                ],
+            ],
         ];
 
         $parser = new Mapper($config);
@@ -763,14 +885,19 @@ public function testArrayItemToColumn()
         );
     }
 
-    public function testObjectToColumnError()
+    /**
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testObjectToColumnError(): void
     {
         $config = [
             'user' => [
                 'mapping' => [
-                    'destination' => 'user'
-                ]
-            ]
+                    'destination' => 'user',
+                ],
+            ],
         ];
 
         $parser = new Mapper($config);
@@ -780,7 +907,13 @@ public function testObjectToColumnError()
         $parser->parse($this->getSampleData());
     }
 
-    public function testDeepNestedTable()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testDeepNestedTable(): void
     {
         $config = [
             'id' => 'id',
@@ -793,27 +926,27 @@ public function testDeepNestedTable()
                         'type' => 'table',
                         'destination' => 'grandchild',
                         'tableMapping' => [
-                            'id' => 'gcid'
-                        ]
-                    ]
-                ]
-            ]
+                            'id' => 'gcid',
+                        ],
+                    ],
+                ],
+            ],
         ];
 
         $data = [
-            (object)[
+            (object) [
                 'id' => 1,
                 'child' => [
-                    (object)[
+                    (object) [
                         'id' => 2,
                         'grandchild' => [
-                            (object)[
-                                'id' => 3
-                            ]
-                        ]
-                    ]
-                ]
-            ]
+                            (object) [
+                                'id' => 3,
+                            ],
+                        ],
+                    ],
+                ],
+            ],
         ];
 
         $parser = new Mapper($config);
@@ -822,16 +955,21 @@ public function testDeepNestedTable()
         $this->assertEquals(['root', 'child', 'grandchild'], array_keys($parser->getCsvFiles()));
     }
 
-    public function testMixedDataError()
+    /**
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    public function testMixedDataError(): void
     {
         $config = [
             'id' => 'id',
             'arr' => [
                 'type' => 'column',
                 'mapping' => [
-                    'destination' => 'arrStr'
-                ]
-            ]
+                    'destination' => 'arrStr',
+                ],
+            ],
         ];
 
         $data = $this->getMixedData();
@@ -843,17 +981,23 @@ public function testMixedDataError()
         $parser->parse($data);
     }
 
-    public function testArrayToString()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testArrayToString(): void
     {
         $config = [
             'id' => 'id',
             'arr' => [
                 'type' => 'column',
                 'mapping' => [
-                    'destination' => 'str'
+                    'destination' => 'str',
                 ],
-                'forceType' => true
-            ]
+                'forceType' => true,
+            ],
         ];
 
         $data = $this->getMixedData();
@@ -864,29 +1008,35 @@ public function testArrayToString()
         $expected = [
             '"id","str"' . PHP_EOL,
             '"1","[1.1,1.2]"' . PHP_EOL,
-            '"2","2.1"' . PHP_EOL
+            '"2","2.1"' . PHP_EOL,
         ];
 
         $this->assertEquals($expected, file($parser->getCsvFiles()['root']->getPathName()));
     }
 
-    public function testStringToArray()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testStringToArray(): void
     {
         $config = [
             'id' => [
                 'mapping' => [
                     'destination' => 'id',
-                    'primaryKey' => true
-                ]
+                    'primaryKey' => true,
+                ],
             ],
             'arr' => [
                 'type' => 'table',
                 'destination' => 'arr',
                 'tableMapping' => [
-                    '.' => 'data'
+                    '.' => 'data',
                 ],
-                'forceType' => true
-            ]
+                'forceType' => true,
+            ],
         ];
 
         $data = $this->getMixedData();
@@ -897,21 +1047,27 @@ public function testStringToArray()
         $root = [
             '"id"' . PHP_EOL,
             '"1"' . PHP_EOL,
-            '"2"' . PHP_EOL
+            '"2"' . PHP_EOL,
         ];
 
         $arr = [
             '"data","root_pk"' . PHP_EOL,
             '"1.1","1"' . PHP_EOL,
             '"1.2","1"' . PHP_EOL,
-            '"2.1","2"' . PHP_EOL
+            '"2.1","2"' . PHP_EOL,
         ];
 
         $this->assertEquals($root, file($parser->getCsvFiles()['root']->getPathName()));
         $this->assertEquals($arr, file($parser->getCsvFiles()['arr']->getPathName()));
     }
 
-    public function testArrayToTable()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testArrayToTable(): void
     {
         $config = [
             'rows' => [
@@ -921,17 +1077,17 @@ public function testArrayToTable()
                     '0' => [
                         'type' => 'column',
                         'mapping' => [
-                            'destination' => 'date'
-                        ]
+                            'destination' => 'date',
+                        ],
                     ],
                     '1' => [
                         'type' => 'column',
                         'mapping' => [
-                            'destination' => 'clicks'
-                        ]
-                    ]
-                ]
-            ]
+                            'destination' => 'clicks',
+                        ],
+                    ],
+                ],
+            ],
         ];
 
         $data = json_decode('[{
@@ -947,13 +1103,19 @@ public function testArrayToTable()
         $expected = [
             '"date","clicks","root_pk"' . PHP_EOL,
             '"2017-05-27","83008","20afe46b23b7afa04d50a036bc3b9021"' . PHP_EOL,
-            '"2017-05-28","105723","20afe46b23b7afa04d50a036bc3b9021"' . PHP_EOL
+            '"2017-05-28","105723","20afe46b23b7afa04d50a036bc3b9021"' . PHP_EOL,
         ];
 
         $this->assertEquals($expected, file($parser->getCsvFiles()['report-rows']->getPathName()));
     }
 
-    public function testDontWriteHeader()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testDontWriteHeader(): void
     {
         $mapping = [
             'id' => 'id',
@@ -969,6 +1131,12 @@ public function testDontWriteHeader()
         $this->assertEquals(['id', 'time'], $file->getHeader());
     }
 
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
     public function testScalarArrayToSeparatedTable(): void
     {
         $mapping = [
@@ -977,23 +1145,23 @@ public function testScalarArrayToSeparatedTable(): void
                 'mapping' => [
                     'destination' => 'id',
                     'primaryKey' => true,
-                ]
+                ],
 
             ],
-            "title" => "title",
+            'title' => 'title',
             'actors' => [
                 'type' => 'table',
                 'destination' => 'actor',
                 'tableMapping' => [
-                    '' => 'name' // <<<<< empty string means "self"
-                ]
+                    '' => 'name', // <<<<< empty string means "self"
+                ],
             ],
         ];
 
         $data = [
-            ["id" => 1, "title" => 'Rush', "actors" => ["Daniel Bruhl", "Chris Hemsworth", "Olivia Wilde"]],
-            ["id" => 2, "title" => 'Prisoners', "actors" => ["Hugh Jackman", "Jake Gyllenhaal", "Viola Davis"]],
-            ["id" => 3, "title" => 'Insidious 2', "actors" => ["Patrick Wilson", "Rose Byrne", "Barbara Hershey"]]
+            ['id' => 1, 'title' => 'Rush', 'actors' => ['Daniel Bruhl', 'Chris Hemsworth', 'Olivia Wilde']],
+            ['id' => 2, 'title' => 'Prisoners', 'actors' => ['Hugh Jackman', 'Jake Gyllenhaal', 'Viola Davis']],
+            ['id' => 3, 'title' => 'Insidious 2', 'actors' => ['Patrick Wilson', 'Rose Byrne', 'Barbara Hershey']],
         ];
 
         $parser = new Mapper($mapping);
@@ -1007,7 +1175,7 @@ public function testScalarArrayToSeparatedTable(): void
             '"id","title"' . PHP_EOL,
             '"1","Rush"' . PHP_EOL,
             '"2","Prisoners"' . PHP_EOL,
-            '"3","Insidious 2"' . PHP_EOL
+            '"3","Insidious 2"' . PHP_EOL,
         ];
         $this->assertEquals($expectedRoot, file($files['root']->getPathName()));
 
@@ -1027,53 +1195,62 @@ public function testScalarArrayToSeparatedTable(): void
         $this->assertEquals($expectedActor, file($files['actor']->getPathName()));
     }
 
-    protected function getMixedData()
+    /**
+     * @return array<int, object>
+     */
+    protected function getMixedData(): array
     {
         return [
-            (object)[
+            (object) [
                 'id' => 1,
                 'arr' => [
                     1.1,
-                    1.2
-                ]
+                    1.2,
+                ],
             ],
-            (object)[ // poor data
+            (object) [ // poor data
                 'id' => 2,
-                'arr' => 2.1
-            ]
+                'arr' => 2.1,
+            ],
         ];
     }
 
-    protected function getSampleData()
+    /**
+     * @return array<int, object>
+     */
+    protected function getSampleData(): array
     {
         return [
-            (object)[
+            (object) [
                 'timestamp' => 1234567890,
                 'id' => 1,
                 'text' => 'asdf',
-                'user' => (object)[
+                'user' => (object) [
                     'id' => 123,
-                    'username' => 'alois'
+                    'username' => 'alois',
                 ],
                 'reactions' => [
-                    (object)[
-                        'user' => (object)[
+                    (object) [
+                        'user' => (object) [
                             'id' => 456,
-                            'username' => 'jose'
-                        ]
+                            'username' => 'jose',
+                        ],
                     ],
-                    (object)[
-                        'user' => (object)[
+                    (object) [
+                        'user' => (object) [
                             'id' => 789,
-                            'username' => 'mike'
-                        ]
-                    ]
-                ]
-            ]
+                            'username' => 'mike',
+                        ],
+                    ],
+                ],
+            ],
         ];
     }
 
-    protected function getSampleDataSimple()
+    /**
+     * @return array<int, array<string, mixed>>
+     */
+    protected function getSampleDataSimple(): array
     {
         $json = <<<JSON
 [
diff --git a/tests/Keboola/CsvMap/MapperWrongPathTest.php b/tests/Keboola/CsvMap/MapperWrongPathTest.php
index ff01828..88a80a3 100644
--- a/tests/Keboola/CsvMap/MapperWrongPathTest.php
+++ b/tests/Keboola/CsvMap/MapperWrongPathTest.php
@@ -1,12 +1,20 @@
 <?php
 
+declare(strict_types=1);
+
 namespace Keboola\CsvMap;
 
 use PHPUnit\Framework\TestCase;
 
 class MapperWrongPathTest extends TestCase
 {
-    public function testParseWrongMain()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testParseWrongMain(): void
     {
         $mapping = [
             'nonExistent1' => 'nonExistent1',
@@ -41,7 +49,13 @@ public function testParseWrongMain()
         $this->assertEquals($expected, file_get_contents($file->getPathname()));
     }
 
-    public function testParseWrongRelation()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     * @throws \Keboola\Csv\Exception
+     */
+    public function testParseWrongRelation(): void
     {
         $mapping = [
             'id' => [
@@ -49,7 +63,7 @@ public function testParseWrongRelation()
                 'mapping' => [
                     'destination' => 'pk',
                     'primaryKey' => true,
-                ]
+                ],
             ],
             'timestamp' => 'timestamp',
             'nonexistent' => [
@@ -58,8 +72,8 @@ public function testParseWrongRelation()
                 'tableMapping' => [
                     'user.id' => 'id',
                     'user.username' => 'username',
-                ]
-            ]
+                ],
+            ],
         ];
 
         // one row
@@ -76,7 +90,6 @@ public function testParseWrongRelation()
         $this->assertFileExists($file1->getPathname());
         $this->assertEquals($expected1, file_get_contents($file1->getPathname()));
 
-
         $file2 = $parser->getCsvFiles()['nonexistent'];
 
         $expected2 = <<<CSV
@@ -101,7 +114,6 @@ public function testParseWrongRelation()
         $this->assertFileExists($file1->getPathname());
         $this->assertEquals($expected1, file_get_contents($file1->getPathname()));
 
-
         $file2 = $parser->getCsvFiles()['nonexistent'];
 
         $expected2 = <<<CSV
@@ -113,7 +125,13 @@ public function testParseWrongRelation()
         $this->assertEquals($expected2, file_get_contents($file2->getPathname()));
     }
 
-    public function testParseWrongBothMainAndRelation()
+    /**
+     * @throws \Keboola\CsvMap\Exception\BadDataException
+     * @throws \Keboola\Utils\Exception
+     * @throws \Keboola\Csv\Exception
+     * @throws \Keboola\CsvMap\Exception\BadConfigException
+     */
+    public function testParseWrongBothMainAndRelation(): void
     {
         $mapping = [
             'nonexistent1' => [
@@ -121,7 +139,7 @@ public function testParseWrongBothMainAndRelation()
                 'mapping' => [
                     'destination' => 'nonexistent1',
                     'primaryKey' => true,
-                ]
+                ],
             ],
             'nonexistent2' => 'nonexistent2',
             'nonexistent3' => [
@@ -130,8 +148,8 @@ public function testParseWrongBothMainAndRelation()
                 'tableMapping' => [
                     'user.id' => 'id',
                     'user.username' => 'username',
-                ]
-            ]
+                ],
+            ],
         ];
 
         // one row
@@ -148,7 +166,6 @@ public function testParseWrongBothMainAndRelation()
         $this->assertFileExists($file1->getPathname());
         $this->assertEquals($expected1, file_get_contents($file1->getPathname()));
 
-
         $file2 = $parser->getCsvFiles()['nonexistent3'];
 
         $expected2 = <<<CSV
@@ -173,7 +190,6 @@ public function testParseWrongBothMainAndRelation()
         $this->assertFileExists($file1->getPathname());
         $this->assertEquals($expected1, file_get_contents($file1->getPathname()));
 
-
         $file2 = $parser->getCsvFiles()['nonexistent3'];
 
         $expected2 = <<<CSV
@@ -185,7 +201,10 @@ public function testParseWrongBothMainAndRelation()
         $this->assertEquals($expected2, file_get_contents($file2->getPathname()));
     }
 
-    protected function getSampleDataSimple()
+    /**
+     * @return array<int, array<string, mixed>>
+     */
+    protected function getSampleDataSimple(): array
     {
         $json = <<<JSON
 [
@@ -199,7 +218,10 @@ protected function getSampleDataSimple()
         return json_decode($json, true);
     }
 
-    protected function getSampleDataMulti()
+    /**
+     * @return array<int, array<string, mixed>>
+     */
+    protected function getSampleDataMulti(): array
     {
         $json = <<<JSON
 [
