Skip to content

Commit 8f1134d

Browse files
authored
Merge branch '2.x-dev' into overhaul-the-authors-feature
2 parents d4f7d95 + ebe55fb commit 8f1134d

File tree

11 files changed

+204
-83
lines changed

11 files changed

+204
-83
lines changed

monorepo/HydeStan/HydeStan.php

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ final class HydeStan
1212
const VERSION = '0.0.0-dev';
1313

1414
private array $files;
15+
private array $testFiles;
1516
private array $errors = [];
1617
private int $scannedLines = 0;
1718
private int $aggregateLines = 0;
@@ -37,10 +38,13 @@ public function __construct(private readonly bool $debug = false)
3738
public function __destruct()
3839
{
3940
$this->console->newline();
40-
$this->console->info(sprintf('HydeStan has exited after scanning %s total (and %s aggregate) lines in %s files. Total expressions analysed: %s',
41+
$this->console->info(sprintf('HydeStan has exited after scanning %s total (and %s aggregate) lines in %s files.',
4142
number_format($this->scannedLines),
4243
number_format($this->aggregateLines),
43-
number_format(count($this->files)),
44+
number_format(count($this->files) + count($this->testFiles)),
45+
));
46+
47+
$this->console->info(sprintf('Total expressions analysed: %s',
4448
number_format(AnalysisStatisticsContainer::getExpressionsAnalysed()),
4549
));
4650

@@ -64,6 +68,8 @@ public function run(): void
6468
$this->analyseFile($file, $this->getFileContents($file));
6569
}
6670

71+
$this->runTestStan();
72+
6773
$endTime = microtime(true) - $time;
6874
$this->console->info(sprintf('HydeStan has finished in %s seconds (%sms) using %s KB RAM',
6975
number_format($endTime, 2),
@@ -112,6 +118,21 @@ private function getFiles(): array
112118
return $files;
113119
}
114120

121+
private function getTestFiles(): array
122+
{
123+
$files = [];
124+
125+
$directory = new RecursiveDirectoryIterator(BASE_PATH.'/tests');
126+
$iterator = new RecursiveIteratorIterator($directory);
127+
$regex = new RegexIterator($iterator, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH);
128+
129+
foreach ($regex as $file) {
130+
$files[] = substr($file[0], strlen(BASE_PATH) + 1);
131+
}
132+
133+
return $files;
134+
}
135+
115136
private function analyseFile(string $file, string $contents): void
116137
{
117138
$fileAnalysers = [
@@ -160,6 +181,51 @@ public static function addActionsMessage(string $level, string $file, int $lineN
160181
// $template = '::warning file={name},line={line},endLine={endLine},title={title}::{message}';
161182
self::$warnings[] = sprintf("::$level file=%s,line=%s,endLine=%s,title=%s::%s", 'packages/framework/'.str_replace('\\', '/', $file), $lineNumber, $lineNumber, $title, $message);
162183
}
184+
185+
protected function runTestStan(): void
186+
{
187+
$this->console->info('TestStan: Analyzing test files...');
188+
189+
$this->testFiles = $this->getTestFiles();
190+
191+
foreach ($this->testFiles as $file) {
192+
$this->analyseTestFile($file, $this->getFileContents($file));
193+
}
194+
195+
$this->console->info('TestStan: Finished analyzing test files!');
196+
}
197+
198+
private function analyseTestFile(string $file, string $contents): void
199+
{
200+
$fileAnalysers = [
201+
new NoFixMeAnalyser($file, $contents),
202+
new NoUsingAssertEqualsForScalarTypesTestAnalyser($file, $contents),
203+
];
204+
205+
foreach ($fileAnalysers as $analyser) {
206+
if ($this->debug) {
207+
$this->console->debugComment('Running '.$analyser::class);
208+
}
209+
210+
$analyser->run($file, $contents);
211+
AnalysisStatisticsContainer::countedLines(substr_count($contents, "\n"));
212+
213+
foreach (explode("\n", $contents) as $lineNumber => $line) {
214+
$lineAnalysers = [
215+
//
216+
];
217+
218+
foreach ($lineAnalysers as $analyser) {
219+
AnalysisStatisticsContainer::countedLine();
220+
$analyser->run($file, $lineNumber, $line);
221+
$this->aggregateLines++;
222+
}
223+
}
224+
}
225+
226+
$this->scannedLines += substr_count($contents, "\n");
227+
$this->aggregateLines += (substr_count($contents, "\n") * count($fileAnalysers));
228+
}
163229
}
164230

165231
abstract class Analyser
@@ -215,6 +281,39 @@ public function run(string $file, string $contents): void
215281
}
216282
}
217283

284+
class NoUsingAssertEqualsForScalarTypesTestAnalyser extends FileAnalyser // Todo: Extend line analyser instead? Would allow for checking for more errors after the first error
285+
{
286+
public function run(string $file, string $contents): void
287+
{
288+
$searches = [
289+
"assertEquals('",
290+
];
291+
292+
foreach ($searches as $search) {
293+
AnalysisStatisticsContainer::analysedExpression();
294+
295+
if (str_contains($contents, $search)) {
296+
// Get line number of marker by counting new \n tags before it
297+
$stringBeforeMarker = substr($contents, 0, strpos($contents, $search));
298+
$lineNumber = substr_count($stringBeforeMarker, "\n") + 1;
299+
300+
// Get the line contents
301+
$line = explode("\n", $contents)[$lineNumber - 1];
302+
303+
// Check for false positives
304+
$commonlyStringCastables = ['$article', '$document', 'getXmlElement()', '$url->loc', '$page->markdown', '$post->data(\'author\')'];
305+
306+
if (check_str_contains_any($commonlyStringCastables, $line)) {
307+
continue;
308+
}
309+
310+
// Todo: Does not work when using objects to string cast, false positive, maybe use warning instead of fail
311+
$this->fail(sprintf('Found %s instead assertSame for scalar type in %s on line %s', trim($search, "()'"), $file, $lineNumber));
312+
}
313+
}
314+
}
315+
}
316+
218317
class UnImportedFunctionAnalyser extends FileAnalyser
219318
{
220319
public function run(string $file, string $contents): void
@@ -319,3 +418,16 @@ public function __construct(string $file, int $lineNumber, string $line);
319418

320419
public function run(string $file, int $lineNumber, string $line): void;
321420
}
421+
422+
function check_str_contains_any(array $searches, string $line): bool
423+
{
424+
$strContainsAny = false;
425+
foreach ($searches as $search) {
426+
AnalysisStatisticsContainer::analysedExpression();
427+
if (str_contains($line, $search)) {
428+
$strContainsAny = true;
429+
}
430+
}
431+
432+
return $strContainsAny;
433+
}

packages/framework/tests/Feature/Services/Markdown/ShortcodeProcessorTest.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,22 @@ public function testDiscoveredShortcodesAreUsedToProcessInput()
2525
{
2626
$processor = new ShortcodeProcessor('>info foo');
2727

28-
$this->assertEquals('<blockquote class="info"><p>foo</p></blockquote>',
29-
$processor->run());
28+
$this->assertSame('<blockquote class="info"><p>foo</p></blockquote>', $processor->run());
3029
}
3130

3231
public function testStringWithoutShortcodeIsNotModified()
3332
{
3433
$processor = new ShortcodeProcessor('foo');
3534

36-
$this->assertEquals('foo', $processor->run());
35+
$this->assertSame('foo', $processor->run());
3736
}
3837

3938
public function testProcessStaticShorthand()
4039
{
41-
$this->assertEquals('<blockquote class="info"><p>foo</p></blockquote>',
42-
ShortcodeProcessor::preprocess('>info foo'));
40+
$this->assertSame(
41+
'<blockquote class="info"><p>foo</p></blockquote>',
42+
ShortcodeProcessor::preprocess('>info foo')
43+
);
4344
}
4445

4546
public function testShortcodesCanBeAddedToProcessor()
@@ -60,7 +61,7 @@ public static function resolve(string $input): string
6061
});
6162

6263
$this->assertArrayHasKey('foo', $processor->getShortcodes());
63-
$this->assertEquals('bar', $processor->run());
64+
$this->assertSame('bar', $processor->run());
6465
}
6566

6667
public function testShortcodesCanBeAddedToProcessorUsingArray()
@@ -81,6 +82,6 @@ public static function resolve(string $input): string
8182
}]);
8283

8384
$this->assertArrayHasKey('foo', $processor->getShortcodes());
84-
$this->assertEquals('bar', $processor->run());
85+
$this->assertSame('bar', $processor->run());
8586
}
8687
}

packages/framework/tests/Feature/Services/RssFeedServiceTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public function testServiceInstantiatesXmlElement()
2828
public function testXmlRootElementIsSetToRss20()
2929
{
3030
$service = new RssFeedGenerator();
31-
$this->assertEquals('rss', $service->getXmlElement()->getName());
31+
$this->assertSame('rss', $service->getXmlElement()->getName());
3232
$this->assertEquals('2.0', $service->getXmlElement()->attributes()->version);
3333
}
3434

packages/framework/tests/Feature/Support/ProjectFileTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,19 @@ public function testCanConstruct()
2121
$this->assertSame('foo', $file->path);
2222
}
2323

24-
public function can_make()
24+
public function testCanMake()
2525
{
2626
$this->assertEquals(new ProjectFileTestClass('foo'), ProjectFileTestClass::make('foo'));
2727
}
2828

2929
public function testCanConstructWithNestedPaths()
3030
{
31-
$this->assertEquals('path/to/file.txt', ProjectFileTestClass::make('path/to/file.txt')->path);
31+
$this->assertSame('path/to/file.txt', ProjectFileTestClass::make('path/to/file.txt')->path);
3232
}
3333

3434
public function testAbsolutePathIsNormalizedToRelative()
3535
{
36-
$this->assertEquals('foo', ProjectFileTestClass::make(Hyde::path('foo'))->path);
36+
$this->assertSame('foo', ProjectFileTestClass::make(Hyde::path('foo'))->path);
3737
}
3838

3939
public function testGetNameReturnsNameOfFile()

packages/framework/tests/Unit/Foundation/HyperlinkFileHelperRelativeLinkTest.php

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,126 +31,126 @@ protected function setUp(): void
3131

3232
public function testHelperReturnsStringAsIsIfCurrentIsNotSet()
3333
{
34-
$this->assertEquals('foo/bar.html', Hyde::relativeLink('foo/bar.html'));
34+
$this->assertSame('foo/bar.html', Hyde::relativeLink('foo/bar.html'));
3535
}
3636

3737
public function testHelperInjectsProperNumberOfDoublesSlash()
3838
{
3939
$this->mockCurrentPage('foo/bar.html');
40-
$this->assertEquals('../foo.html', Hyde::relativeLink('foo.html'));
40+
$this->assertSame('../foo.html', Hyde::relativeLink('foo.html'));
4141
}
4242

4343
public function testHelperInjectsProperNumberOfDoublesSlashForDeeplyNestedPaths()
4444
{
4545
$this->mockCurrentPage('foo/bar/baz/qux.html');
46-
$this->assertEquals('../../../foo.html', Hyde::relativeLink('foo.html'));
46+
$this->assertSame('../../../foo.html', Hyde::relativeLink('foo.html'));
4747
}
4848

4949
public function testHelperHandlesDestinationWithoutFileExtension()
5050
{
5151
$this->mockCurrentPage('foo/bar.html');
52-
$this->assertEquals('../foo', Hyde::relativeLink('foo'));
52+
$this->assertSame('../foo', Hyde::relativeLink('foo'));
5353
}
5454

5555
public function testHelperHandlesCurrentWithoutFileExtension()
5656
{
5757
$this->mockCurrentPage('foo/bar');
58-
$this->assertEquals('../foo.html', Hyde::relativeLink('foo.html'));
58+
$this->assertSame('../foo.html', Hyde::relativeLink('foo.html'));
5959
}
6060

6161
public function testHelperHandlesCaseWithoutAnyFileExtensions()
6262
{
6363
$this->mockCurrentPage('foo/bar');
64-
$this->assertEquals('../foo', Hyde::relativeLink('foo'));
64+
$this->assertSame('../foo', Hyde::relativeLink('foo'));
6565
}
6666

6767
public function testHelperHandlesCaseWithMixedFileExtensions()
6868
{
6969
$this->mockCurrentPage('foo/bar.md');
70-
$this->assertEquals('../foo.md', Hyde::relativeLink('foo.md'));
70+
$this->assertSame('../foo.md', Hyde::relativeLink('foo.md'));
7171
$this->mockCurrentPage('foo/bar.txt');
72-
$this->assertEquals('../foo.txt', Hyde::relativeLink('foo.txt'));
72+
$this->assertSame('../foo.txt', Hyde::relativeLink('foo.txt'));
7373
}
7474

7575
public function testHelperHandlesDifferentFileExtensions()
7676
{
7777
$this->mockCurrentPage('foo/bar');
78-
$this->assertEquals('../foo.png', Hyde::relativeLink('foo.png'));
79-
$this->assertEquals('../foo.css', Hyde::relativeLink('foo.css'));
80-
$this->assertEquals('../foo.js', Hyde::relativeLink('foo.js'));
78+
$this->assertSame('../foo.png', Hyde::relativeLink('foo.png'));
79+
$this->assertSame('../foo.css', Hyde::relativeLink('foo.css'));
80+
$this->assertSame('../foo.js', Hyde::relativeLink('foo.js'));
8181
}
8282

8383
public function testHelperReturnsPrettyUrlIfEnabledAndDestinationIsAHtmlFile()
8484
{
8585
self::mockConfig(['hyde.pretty_urls' => true]);
8686
$this->mockCurrentPage('foo/bar.html');
87-
$this->assertEquals('../foo', Hyde::relativeLink('foo.html'));
87+
$this->assertSame('../foo', Hyde::relativeLink('foo.html'));
8888
}
8989

9090
public function testHelperMethodDoesNotRequireCurrentPathToBeHtmlToUsePrettyUrls()
9191
{
9292
self::mockConfig(['hyde.pretty_urls' => true]);
9393
$this->mockCurrentPage('foo/bar');
94-
$this->assertEquals('../foo', Hyde::relativeLink('foo.html'));
94+
$this->assertSame('../foo', Hyde::relativeLink('foo.html'));
9595
}
9696

9797
public function testHelperReturnsDoesNotReturnPrettyUrlIfWhenEnabledButAndDestinationIsNotAHtmlFile()
9898
{
9999
self::mockConfig(['hyde.pretty_urls' => true]);
100100
$this->mockCurrentPage('foo/bar.html');
101-
$this->assertEquals('../foo.png', Hyde::relativeLink('foo.png'));
101+
$this->assertSame('../foo.png', Hyde::relativeLink('foo.png'));
102102
}
103103

104104
public function testHelperRewritesIndexWhenUsingPrettyUrls()
105105
{
106106
self::mockConfig(['hyde.pretty_urls' => true]);
107107
$this->mockCurrentPage('foo.html');
108-
$this->assertEquals('./', Hyde::relativeLink('index.html'));
108+
$this->assertSame('./', Hyde::relativeLink('index.html'));
109109
$this->mockCurrentPage('foo/bar.html');
110-
$this->assertEquals('../', Hyde::relativeLink('index.html'));
110+
$this->assertSame('../', Hyde::relativeLink('index.html'));
111111
$this->mockCurrentPage('foo/bar/baz.html');
112-
$this->assertEquals('../../', Hyde::relativeLink('index.html'));
112+
$this->assertSame('../../', Hyde::relativeLink('index.html'));
113113
}
114114

115115
public function testHelperDoesNotRewriteIndexWhenNotUsingPrettyUrls()
116116
{
117117
self::mockConfig(['hyde.pretty_urls' => false]);
118118
$this->mockCurrentPage('foo.html');
119-
$this->assertEquals('index.html', Hyde::relativeLink('index.html'));
119+
$this->assertSame('index.html', Hyde::relativeLink('index.html'));
120120
$this->mockCurrentPage('foo/bar.html');
121-
$this->assertEquals('../index.html', Hyde::relativeLink('index.html'));
121+
$this->assertSame('../index.html', Hyde::relativeLink('index.html'));
122122
$this->mockCurrentPage('foo/bar/baz.html');
123-
$this->assertEquals('../../index.html', Hyde::relativeLink('index.html'));
123+
$this->assertSame('../../index.html', Hyde::relativeLink('index.html'));
124124
}
125125

126126
public function testHelperRewritesDocumentationPageIndexWhenUsingPrettyUrls()
127127
{
128128
self::mockConfig(['hyde.pretty_urls' => true]);
129129
$this->mockCurrentPage('foo.html');
130-
$this->assertEquals('docs/', Hyde::relativeLink('docs/index.html'));
130+
$this->assertSame('docs/', Hyde::relativeLink('docs/index.html'));
131131
$this->mockCurrentPage('docs.html');
132-
$this->assertEquals('docs/', Hyde::relativeLink('docs/index.html'));
132+
$this->assertSame('docs/', Hyde::relativeLink('docs/index.html'));
133133
$this->mockCurrentPage('foo/bar.html');
134-
$this->assertEquals('../docs/', Hyde::relativeLink('docs/index.html'));
134+
$this->assertSame('../docs/', Hyde::relativeLink('docs/index.html'));
135135
$this->mockCurrentPage('docs/foo.html');
136-
$this->assertEquals('../docs/', Hyde::relativeLink('docs/index.html'));
136+
$this->assertSame('../docs/', Hyde::relativeLink('docs/index.html'));
137137
}
138138

139139
public function testHelperDoesNotRewriteDocumentationPageIndexWhenNotUsingPrettyUrls()
140140
{
141141
self::mockConfig(['hyde.pretty_urls' => false]);
142142
$this->mockCurrentPage('foo.html');
143-
$this->assertEquals('docs/index.html', Hyde::relativeLink('docs/index.html'));
143+
$this->assertSame('docs/index.html', Hyde::relativeLink('docs/index.html'));
144144
$this->mockCurrentPage('docs.html');
145-
$this->assertEquals('docs/index.html', Hyde::relativeLink('docs/index.html'));
145+
$this->assertSame('docs/index.html', Hyde::relativeLink('docs/index.html'));
146146
$this->mockCurrentPage('foo/bar.html');
147-
$this->assertEquals('../docs/index.html', Hyde::relativeLink('docs/index.html'));
147+
$this->assertSame('../docs/index.html', Hyde::relativeLink('docs/index.html'));
148148
$this->mockCurrentPage('docs/foo.html');
149-
$this->assertEquals('../docs/index.html', Hyde::relativeLink('docs/index.html'));
149+
$this->assertSame('../docs/index.html', Hyde::relativeLink('docs/index.html'));
150150
}
151151

152152
public function testHelperDoesNotRewriteAlreadyProcessedLinks()
153153
{
154-
$this->assertEquals('../foo', Hyde::relativeLink('../foo'));
154+
$this->assertSame('../foo', Hyde::relativeLink('../foo'));
155155
}
156156
}

0 commit comments

Comments
 (0)