Skip to content

Commit e94fb42

Browse files
Add relative file path to ClassDescription (#477)
Here a $filePath attribute is added to the ClassDescription and is populated during the parsing process
1 parent c61405a commit e94fb42

37 files changed

+205
-100
lines changed

src/Analyzer/ClassDescription.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ class ClassDescription
88
{
99
private FullyQualifiedClassName $FQCN;
1010

11+
private string $filePath;
12+
1113
/** @var list<ClassDependency> */
1214
private array $dependencies;
1315

@@ -53,10 +55,12 @@ public function __construct(
5355
bool $interface,
5456
bool $trait,
5557
bool $enum,
56-
array $docBlock = [],
57-
array $attributes = []
58+
array $docBlock,
59+
array $attributes,
60+
string $filePath
5861
) {
5962
$this->FQCN = $FQCN;
63+
$this->filePath = $filePath;
6064
$this->dependencies = $dependencies;
6165
$this->interfaces = $interfaces;
6266
$this->extends = $extends;
@@ -70,10 +74,11 @@ public function __construct(
7074
$this->enum = $enum;
7175
}
7276

73-
public static function getBuilder(string $FQCN): ClassDescriptionBuilder
77+
public static function getBuilder(string $FQCN, string $filePath): ClassDescriptionBuilder
7478
{
7579
$cb = new ClassDescriptionBuilder();
7680
$cb->setClassName($FQCN);
81+
$cb->setFilePath($filePath);
7782

7883
return $cb;
7984
}
@@ -88,6 +93,11 @@ public function getFQCN(): string
8893
return $this->FQCN->toString();
8994
}
9095

96+
public function getFilePath(): string
97+
{
98+
return $this->filePath;
99+
}
100+
91101
public function namespaceMatches(string $pattern): bool
92102
{
93103
return $this->FQCN->matches($pattern);

src/Analyzer/ClassDescriptionBuilder.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ class ClassDescriptionBuilder
3636

3737
private bool $enum = false;
3838

39+
private ?string $filePath = null;
40+
3941
public function clear(): void
4042
{
4143
$this->FQCN = null;
@@ -52,6 +54,13 @@ public function clear(): void
5254
$this->enum = false;
5355
}
5456

57+
public function setFilePath(?string $filePath): self
58+
{
59+
$this->filePath = $filePath;
60+
61+
return $this;
62+
}
63+
5564
public function setClassName(string $FQCN): self
5665
{
5766
$this->FQCN = FullyQualifiedClassName::fromString($FQCN);
@@ -142,6 +151,7 @@ public function addAttribute(string $FQCN, int $line): self
142151
public function build(): ClassDescription
143152
{
144153
Assert::notNull($this->FQCN, 'You must set an FQCN');
154+
Assert::notNull($this->filePath, 'You must set a file path');
145155

146156
return new ClassDescription(
147157
$this->FQCN,
@@ -155,7 +165,8 @@ public function build(): ClassDescription
155165
$this->trait,
156166
$this->enum,
157167
$this->docBlock,
158-
$this->attributes
168+
$this->attributes,
169+
$this->filePath
159170
);
160171
}
161172
}

src/Analyzer/FileParser.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public function parse(string $fileContent, string $filename): void
5050
$this->parsingErrors = [];
5151
try {
5252
$this->fileVisitor->clearParsedClassDescriptions();
53+
$this->fileVisitor->setFilePath($filename);
5354

5455
$errorHandler = new Collecting();
5556
$stmts = $this->parser->parse($fileContent, $errorHandler);

src/Analyzer/FileVisitor.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ public function __construct(ClassDescriptionBuilder $classDescriptionBuilder)
2121
$this->classDescriptionBuilder = $classDescriptionBuilder;
2222
}
2323

24+
public function setFilePath(string $filePath): void
25+
{
26+
$this->classDescriptionBuilder->setFilePath($filePath);
27+
}
28+
2429
public function enterNode(Node $node): void
2530
{
2631
if ($node instanceof Node\Stmt\Class_) {
@@ -224,6 +229,7 @@ public function getClassDescriptions(): array
224229
public function clearParsedClassDescriptions(): void
225230
{
226231
$this->classDescriptions = [];
232+
$this->classDescriptionBuilder->setFilePath(null);
227233
$this->classDescriptionBuilder->clear();
228234
}
229235

tests/Unit/Analyzer/ClassDescriptionBuilderTest.php

Lines changed: 63 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@ class ClassDescriptionBuilderTest extends TestCase
1515
public function test_it_should_create_builder_with_dependency_and_interface(): void
1616
{
1717
$FQCN = 'HappyIsland';
18-
$classDescriptionBuilder = new ClassDescriptionBuilder();
19-
$classDescriptionBuilder->setClassName($FQCN);
2018

21-
$classDependency = new ClassDependency('DepClass', 10);
22-
23-
$classDescriptionBuilder->addDependency($classDependency);
24-
$classDescriptionBuilder->addInterface('InterfaceClass', 10);
25-
26-
$classDescription = $classDescriptionBuilder->build();
19+
$classDescription = (new ClassDescriptionBuilder())
20+
->setFilePath('src/Foo.php')
21+
->setClassName($FQCN)
22+
->addDependency(new ClassDependency('DepClass', 10))
23+
->addInterface('InterfaceClass', 10)
24+
->build();
2725

2826
$this->assertInstanceOf(ClassDescription::class, $classDescription);
2927

@@ -34,11 +32,12 @@ public function test_it_should_create_builder_with_dependency_and_interface(): v
3432
public function test_it_should_create_final_class(): void
3533
{
3634
$FQCN = 'HappyIsland';
37-
$classDescriptionBuilder = new ClassDescriptionBuilder();
38-
$classDescriptionBuilder->setClassName($FQCN);
39-
$classDescriptionBuilder->setFinal(true);
4035

41-
$classDescription = $classDescriptionBuilder->build();
36+
$classDescription = (new ClassDescriptionBuilder())
37+
->setFilePath('src/Foo.php')
38+
->setClassName($FQCN)
39+
->setFinal(true)
40+
->build();
4241

4342
$this->assertInstanceOf(ClassDescription::class, $classDescription);
4443

@@ -48,11 +47,12 @@ public function test_it_should_create_final_class(): void
4847
public function test_it_should_create_not_final_class(): void
4948
{
5049
$FQCN = 'HappyIsland';
51-
$classDescriptionBuilder = new ClassDescriptionBuilder();
52-
$classDescriptionBuilder->setClassName($FQCN);
53-
$classDescriptionBuilder->setFinal(false);
5450

55-
$classDescription = $classDescriptionBuilder->build();
51+
$classDescription = (new ClassDescriptionBuilder())
52+
->setFilePath('src/Foo.php')
53+
->setClassName($FQCN)
54+
->setFinal(false)
55+
->build();
5656

5757
$this->assertInstanceOf(ClassDescription::class, $classDescription);
5858

@@ -62,11 +62,12 @@ public function test_it_should_create_not_final_class(): void
6262
public function test_it_should_create_abstract_class(): void
6363
{
6464
$FQCN = 'HappyIsland';
65-
$classDescriptionBuilder = new ClassDescriptionBuilder();
66-
$classDescriptionBuilder->setClassName($FQCN);
67-
$classDescriptionBuilder->setAbstract(true);
6865

69-
$classDescription = $classDescriptionBuilder->build();
66+
$classDescription = (new ClassDescriptionBuilder())
67+
->setFilePath('src/Foo.php')
68+
->setClassName($FQCN)
69+
->setAbstract(true)
70+
->build();
7071

7172
$this->assertInstanceOf(ClassDescription::class, $classDescription);
7273

@@ -76,11 +77,12 @@ public function test_it_should_create_abstract_class(): void
7677
public function test_it_should_create_not_abstract_class(): void
7778
{
7879
$FQCN = 'HappyIsland';
79-
$classDescriptionBuilder = new ClassDescriptionBuilder();
80-
$classDescriptionBuilder->setClassName($FQCN);
81-
$classDescriptionBuilder->setAbstract(false);
8280

83-
$classDescription = $classDescriptionBuilder->build();
81+
$classDescription = (new ClassDescriptionBuilder())
82+
->setFilePath('src/Foo.php')
83+
->setClassName($FQCN)
84+
->setAbstract(false)
85+
->build();
8486

8587
$this->assertInstanceOf(ClassDescription::class, $classDescription);
8688

@@ -90,32 +92,32 @@ public function test_it_should_create_not_abstract_class(): void
9092
public function test_it_should_create_annotated_class(): void
9193
{
9294
$FQCN = 'HappyIsland';
93-
$classDescriptionBuilder = new ClassDescriptionBuilder();
94-
$classDescriptionBuilder->setClassName($FQCN);
95-
$classDescriptionBuilder->addDocBlock('/**
96-
* @psalm-immutable
97-
*/');
9895

99-
$classDescription = $classDescriptionBuilder->build();
96+
$docBlock = <<< 'EOT'
97+
/**
98+
* @psalm-immutable
99+
*/
100+
EOT;
100101

101-
$this->assertInstanceOf(ClassDescription::class, $classDescription);
102+
$classDescription = (new ClassDescriptionBuilder())
103+
->setFilePath('src/Foo.php')
104+
->setClassName($FQCN)
105+
->addDocBlock($docBlock)
106+
->build();
102107

103-
$this->assertEquals(
104-
['/**
105-
* @psalm-immutable
106-
*/'],
107-
$classDescription->getDocBlock()
108-
);
108+
$this->assertInstanceOf(ClassDescription::class, $classDescription);
109+
$this->assertEquals([$docBlock], $classDescription->getDocBlock());
109110
}
110111

111112
public function test_it_should_add_attributes(): void
112113
{
113114
$FQCN = 'HappyIsland';
114-
$classDescriptionBuilder = new ClassDescriptionBuilder();
115-
$classDescriptionBuilder->setClassName($FQCN);
116-
$classDescriptionBuilder->addAttribute('AttrClass', 27);
117115

118-
$classDescription = $classDescriptionBuilder->build();
116+
$classDescription = (new ClassDescriptionBuilder())
117+
->setFilePath('src/Foo.php')
118+
->setClassName($FQCN)
119+
->addAttribute('AttrClass', 27)
120+
->build();
119121

120122
self::assertEquals(
121123
[FullyQualifiedClassName::fromString('AttrClass')],
@@ -126,56 +128,56 @@ public function test_it_should_add_attributes(): void
126128
public function test_it_should_create_interface(): void
127129
{
128130
$FQCN = 'HappyIsland';
129-
$classDescriptionBuilder = new ClassDescriptionBuilder();
130-
$classDescriptionBuilder->setClassName($FQCN);
131-
$classDescriptionBuilder->setInterface(true);
132131

133-
$classDescription = $classDescriptionBuilder->build();
132+
$classDescription = (new ClassDescriptionBuilder())
133+
->setFilePath('src/Foo.php')
134+
->setClassName($FQCN)
135+
->setInterface(true)
136+
->build();
134137

135138
$this->assertInstanceOf(ClassDescription::class, $classDescription);
136-
137139
$this->assertTrue($classDescription->isInterface());
138140
}
139141

140142
public function test_it_should_create_not_interface(): void
141143
{
142144
$FQCN = 'HappyIsland';
143-
$classDescriptionBuilder = new ClassDescriptionBuilder();
144-
$classDescriptionBuilder->setClassName($FQCN);
145-
$classDescriptionBuilder->setInterface(false);
146145

147-
$classDescription = $classDescriptionBuilder->build();
146+
$classDescription = (new ClassDescriptionBuilder())
147+
->setFilePath('src/Foo.php')
148+
->setClassName($FQCN)
149+
->setInterface(false)
150+
->build();
148151

149152
$this->assertInstanceOf(ClassDescription::class, $classDescription);
150-
151153
$this->assertFalse($classDescription->isInterface());
152154
}
153155

154156
public function test_it_should_create_trait(): void
155157
{
156158
$FQCN = 'HappyIsland';
157-
$classDescriptionBuilder = new ClassDescriptionBuilder();
158-
$classDescriptionBuilder->setClassName($FQCN);
159-
$classDescriptionBuilder->setTrait(true);
160159

161-
$classDescription = $classDescriptionBuilder->build();
160+
$classDescription = (new ClassDescriptionBuilder())
161+
->setFilePath('src/Foo.php')
162+
->setClassName($FQCN)
163+
->setTrait(true)
164+
->build();
162165

163166
$this->assertInstanceOf(ClassDescription::class, $classDescription);
164-
165167
$this->assertTrue($classDescription->isTrait());
166168
}
167169

168170
public function test_it_should_create_not_trait(): void
169171
{
170172
$FQCN = 'HappyIsland';
171-
$classDescriptionBuilder = new ClassDescriptionBuilder();
172-
$classDescriptionBuilder->setClassName($FQCN);
173-
$classDescriptionBuilder->setTrait(false);
174173

175-
$classDescription = $classDescriptionBuilder->build();
174+
$classDescription = (new ClassDescriptionBuilder())
175+
->setFilePath('src/Foo.php')
176+
->setClassName($FQCN)
177+
->setTrait(false)
178+
->build();
176179

177180
$this->assertInstanceOf(ClassDescription::class, $classDescription);
178-
179181
$this->assertFalse($classDescription->isTrait());
180182
}
181183
}

tests/Unit/Analyzer/ClassDescriptionTest.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,18 @@
1010

1111
class ClassDescriptionTest extends TestCase
1212
{
13-
/** @var ClassDescriptionBuilder */
14-
private $builder;
13+
private ClassDescriptionBuilder $builder;
1514

1615
protected function setUp(): void
1716
{
18-
$this->builder = ClassDescription::getBuilder('Fruit\Banana');
17+
$this->builder = ClassDescription::getBuilder('Fruit\Banana', 'src/Foo.php');
18+
}
19+
20+
public function test_should_return_file_path(): void
21+
{
22+
$cd = $this->builder->build();
23+
24+
$this->assertEquals('src/Foo.php', $cd->getFilePath());
1925
}
2026

2127
public function test_should_return_true_if_there_class_is_in_namespace(): void

tests/Unit/Analyzer/FileParserTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public function test_parse_file(): void
2626
$traverser->addVisitor($nameResolver);
2727
$traverser->addVisitor($fileVisitor);
2828

29+
$fileVisitor->setFilePath('foo')->shouldBeCalled();
2930
$fileVisitor->clearParsedClassDescriptions()->shouldBeCalled();
3031

3132
$fileParser = new FileParser(
@@ -52,6 +53,7 @@ public function test_parse_file_with_name_match(): void
5253
$traverser->addVisitor($nameResolver);
5354
$traverser->addVisitor($fileVisitor);
5455

56+
$fileVisitor->setFilePath('foo')->shouldBeCalled();
5557
$fileVisitor->clearParsedClassDescriptions()->shouldBeCalled();
5658

5759
$fileParser = new FileParser(

tests/Unit/Expressions/ForClasses/ContainDocBlockLikeTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public function test_it_should_return_true_if_contains_doc_block(): void
1616
$expression = new ContainDocBlockLike('myDocBlock');
1717

1818
$classDescription = (new ClassDescriptionBuilder())
19+
->setFilePath('src/Foo.php')
1920
->setClassName('HappyIsland\Myclass')
2021
->addDocBlock('/** */myDocBlock with other information')
2122
->build();
@@ -36,6 +37,7 @@ public function test_it_should_return_false_if_not_contains_doc_block(): void
3637
$expression = new ContainDocBlockLike('anotherDocBlock');
3738

3839
$classDescription = (new ClassDescriptionBuilder())
40+
->setFilePath('src/Foo.php')
3941
->setClassName('HappyIsland\Myclass')
4042
->addDocBlock('/** */myDocBlock with other information')
4143
->build();

0 commit comments

Comments
 (0)