-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* chore(tests): add fixture path helper * chore(tests): add syntax error fixture * feat(analyzer): add file analyzer
- Loading branch information
Showing
5 changed files
with
192 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Symblaze\MareScan\Analyzer; | ||
|
||
interface AnalyzerInterface | ||
{ | ||
public function analyze(array $data): array; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Symblaze\MareScan\Analyzer; | ||
|
||
use Symblaze\MareScan\Exception\InspectionError; | ||
use Symblaze\MareScan\Exception\ParserError; | ||
use Symblaze\MareScan\Inspector\InspectorInterface; | ||
use Symblaze\MareScan\Inspector\TypeCompatibility\MissingDeclareStrictTypesInspector; | ||
use Symblaze\MareScan\Parser\ParserInterface; | ||
|
||
final readonly class FileAnalyzer implements AnalyzerInterface | ||
{ | ||
public function __construct(private ParserInterface $parser) | ||
{ | ||
} | ||
|
||
public function analyze(array $data): array | ||
{ | ||
$filePath = $data['path'] ?? null; | ||
|
||
if (! is_string($filePath) || ! file_exists($filePath)) { | ||
return []; | ||
} | ||
|
||
$content = (string)file_get_contents($filePath); | ||
try { | ||
$statements = $this->parser->parse($content); | ||
} catch (ParserError $e) { | ||
return [$this->parserErrorToResult($e, $filePath)]; | ||
} | ||
|
||
$firstStatement = $statements[0] ?? null; | ||
$inspector = new MissingDeclareStrictTypesInspector($firstStatement); | ||
try { | ||
$inspector->inspect(); | ||
} catch (InspectionError $e) { | ||
return [$this->inspectionErrorToResult($e, $filePath, $inspector)]; | ||
} | ||
|
||
return []; | ||
} | ||
|
||
private function parserErrorToResult(ParserError $e, string $filePath): array | ||
{ | ||
return [ | ||
'severity' => 'error', | ||
'message' => $e->getMessage(), | ||
'file' => $filePath, | ||
'description' => 'Parser error occurred while parsing the file', | ||
]; | ||
} | ||
|
||
private function inspectionErrorToResult(InspectionError $e, string $filePath, InspectorInterface $inspector): array | ||
{ | ||
return [ | ||
'severity' => 'warning', | ||
'message' => $e->getMessage(), | ||
'file' => $filePath, | ||
'description' => $inspector->description(), | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Symblaze\MareScan\Tests\Analyzer; | ||
|
||
use PHPUnit\Framework\Attributes\CoversClass; | ||
use PHPUnit\Framework\Attributes\Test; | ||
use Symblaze\MareScan\Analyzer\FileAnalyzer; | ||
use Symblaze\MareScan\Inspector\TypeCompatibility\MissingDeclareStrictTypesInspector; | ||
use Symblaze\MareScan\Parser\ParserBuilder; | ||
use Symblaze\MareScan\Tests\TestCase; | ||
|
||
#[CoversClass(FileAnalyzer::class)] | ||
final class FileAnalyzerTest extends TestCase | ||
{ | ||
#[Test] | ||
public function it_can_detect_syntax_error(): void | ||
{ | ||
$filePath = $this->fixturePath('misc/syntax_error.stub'); | ||
$parser = ParserBuilder::init()->build(); | ||
$sut = new FileAnalyzer($parser); | ||
$data = [ | ||
'path' => $filePath, | ||
'type' => 'file', | ||
]; | ||
|
||
$result = $sut->analyze($data); | ||
|
||
$expected = [ | ||
[ | ||
'severity' => 'error', | ||
'description' => 'Parser error occurred while parsing the file', | ||
'message' => 'Syntax error, unexpected T_ENCAPSED_AND_WHITESPACE on line 3', | ||
'file' => $filePath, | ||
], | ||
]; | ||
$this->assertEqualsCanonicalizing($expected, $result); | ||
} | ||
|
||
#[Test] | ||
public function it_can_detect_missing_strict_types_declaration(): void | ||
{ | ||
$filePath = $this->fixturePath('type_compatibility/missing_declare_strict_types.php'); | ||
$parser = ParserBuilder::init()->build(); | ||
$data = [ | ||
'path' => $filePath, | ||
'type' => 'file', | ||
]; | ||
$sut = new FileAnalyzer($parser); | ||
|
||
$result = $sut->analyze($data); | ||
|
||
$inspector = new MissingDeclareStrictTypesInspector(); | ||
$expected = [ | ||
[ | ||
'severity' => 'warning', | ||
'message' => 'Strict types declaration is missing', | ||
'file' => $filePath, | ||
'description' => $inspector->description(), | ||
], | ||
]; | ||
$this->assertEqualsCanonicalizing($expected, $result); | ||
} | ||
|
||
#[Test] | ||
public function it_can_detect_invalid_declare_strict_types(): void | ||
{ | ||
$filePath = $this->fixturePath('type_compatibility/invalid_declare_strict_types.php'); | ||
$parser = ParserBuilder::init()->build(); | ||
$data = [ | ||
'path' => $filePath, | ||
'type' => 'file', | ||
]; | ||
$sut = new FileAnalyzer($parser); | ||
|
||
$result = $sut->analyze($data); | ||
|
||
$inspector = new MissingDeclareStrictTypesInspector(); | ||
$expected = [ | ||
[ | ||
'severity' => 'warning', | ||
'message' => 'Strict types declaration is missing', | ||
'file' => $filePath, | ||
'description' => $inspector->description(), | ||
], | ||
]; | ||
$this->assertEqualsCanonicalizing($expected, $result); | ||
} | ||
|
||
#[Test] | ||
public function it_can_detect_valid_declare_strict_types(): void | ||
{ | ||
$filePath = $this->fixturePath('type_compatibility/valid_declare_strict_types.php'); | ||
$parser = ParserBuilder::init()->build(); | ||
$data = [ | ||
'path' => $filePath, | ||
'type' => 'file', | ||
]; | ||
$sut = new FileAnalyzer($parser); | ||
|
||
$result = $sut->analyze($data); | ||
|
||
$this->assertEmpty($result); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<?php | ||
|
||
$a = ' |