Skip to content

Commit 2d83ee8

Browse files
authored
Merge pull request #44 from smeghead/class-diagram-classname-with-summary
Class diagram classname with summary
2 parents 4ea6e81 + 9f21af7 commit 2d83ee8

File tree

15 files changed

+233
-24
lines changed

15 files changed

+233
-24
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### Features
44

55
* Added a division diagram to the output when the --dig-diagram option is specified.
6+
* Display a summary of the class Document Comment under the class name in the class diagram.
67

78
## v0.5.0 (2023-03-12)
89

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ OPTIONS
6464
--disable-class-properties not describe properties in class diagram.
6565
--enable-class-methods describe methods in class diagram. (default)
6666
--disable-class-methods not describe methods in class diagram.
67+
--enable-class-name-summary describe classname with Class summary of document comment. (default)
68+
--disable-class-name-summary describe classname without Class summary of document comment.
6769
--php5 parse php source file as php5.
6870
--php7 parse php source file as php7.
6971
--php8 parse php source file as php8. (not suppoted)

bin/php-class-diagram

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ $options = getopt('hv',[
2020
'disable-class-properties',
2121
'enable-class-methods',
2222
'disable-class-methods',
23+
'enable-class-name-summary',
24+
'disable-class-name-summary',
2325
'php7',
2426
'php8',
2527
'header::',
@@ -34,22 +36,24 @@ usage: php-class-diagram [OPTIONS] <target php source directory>
3436
A CLI tool that parses the PHP source directory and outputs PlantUML class diagram scripts.
3537
3638
OPTIONS
37-
-h, --help show this help page.
38-
-v, --version show version.
39-
--class-diagram output class diagram script. (default)
40-
--package-diagram output package diagram script.
41-
--division-diagram output division diagram script.
42-
--jig-diagram output class diagram and package diagram and division diagram script.
43-
--enable-class-properties describe properties in class diagram. (default)
44-
--disable-class-properties not describe properties in class diagram.
45-
--enable-class-methods describe methods in class diagram. (default)
46-
--disable-class-methods not describe methods in class diagram.
47-
--php5 parse php source file as php5.
48-
--php7 parse php source file as php7.
49-
--php8 parse php source file as php8. (not suppoted)
50-
--header='header string' additional header string. You can specify multiple header values.
51-
--include='wildcard' include target file pattern. (default: `*.php`) You can specify multiple include patterns.
52-
--exclude='wildcard' exclude target file pattern. You can specify multiple exclude patterns.
39+
-h, --help show this help page.
40+
-v, --version show version.
41+
--class-diagram output class diagram script. (default)
42+
--package-diagram output package diagram script.
43+
--division-diagram output division diagram script.
44+
--jig-diagram output class diagram and package diagram and division diagram script.
45+
--enable-class-properties describe properties in class diagram. (default)
46+
--disable-class-properties not describe properties in class diagram.
47+
--enable-class-methods describe methods in class diagram. (default)
48+
--disable-class-methods not describe methods in class diagram.
49+
--enable-class-name-summary describe classname with Class summary of document comment. (default)
50+
--disable-class-name-summary describe classname without Class summary of document comment.
51+
--php5 parse php source file as php5.
52+
--php7 parse php source file as php7.
53+
--php8 parse php source file as php8. (not suppoted)
54+
--header='header string' additional header string. You can specify multiple header values.
55+
--include='wildcard' include target file pattern. (default: `*.php`) You can specify multiple include patterns.
56+
--exclude='wildcard' exclude target file pattern. You can specify multiple exclude patterns.
5357
5458
EOS;
5559

src/Config/Options.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,18 @@ public function classMethods(): bool
7575
return true;
7676
}
7777

78+
public function classNameSummary(): bool
79+
{
80+
if (isset($this->opt['enable-class-name-summary'])) {
81+
return true;
82+
}
83+
if (isset($this->opt['disable-class-name-summary'])) {
84+
return false;
85+
}
86+
// default
87+
return true;
88+
}
89+
7890
public function phpVersion(): string
7991
{
8092
if (isset($this->opt['php5'])) {

src/DiagramElement/Entry.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,18 @@ public function dump($level = 0): array
4646
{
4747
$indent = str_repeat(' ', $level);
4848
$lines = [];
49-
// $meta = $this->class->getClassType()->getMeta() === 'Stmt_Interface' ? 'interface' : 'class';
5049
$meta = $this->class->getClassType()->getMetaName();
50+
$classSummary = ($this->options->classNameSummary()
51+
? $this->class->getDescription()
52+
: '');
53+
$classIdentifier = sprintf(
54+
'%s "%s" as %s',
55+
$meta,
56+
$this->class->getClassType()->getName() . (empty($classSummary) ? '' : sprintf("\\n<b>%s</b>", $classSummary)),
57+
$this->class->getClassNameAlias()
58+
);
5159
if ($this->options->classProperties() || $this->options->classMethods()) {
52-
$lines[] = sprintf('%s%s "%s" as %s {', $indent, $meta, $this->class->getClassType()->getName(), $this->class->getClassNameAlias());
60+
$lines[] = sprintf('%s%s {', $indent, $classIdentifier);
5361
if ($this->options->classProperties()) {
5462
foreach ($this->class->getProperties() as $p) {
5563
$lines[] = sprintf(' %s%s%s : %s', $indent, $this->modifier($p->getAccessModifier()), $p->getName(), $p->getType()->getName());
@@ -65,7 +73,7 @@ public function dump($level = 0): array
6573
}
6674
$lines[] = sprintf('%s}', $indent);
6775
} else {
68-
$lines[] = sprintf('%s%s "%s" as %s', $indent, $meta, $this->class->getClassType()->getName(), $this->class->getClassNameAlias());
76+
$lines[] = sprintf('%s%s', $indent, $classIdentifier);
6977
}
7078
return $lines;
7179
}
@@ -84,7 +92,7 @@ public function dumpDivisions($level = 0): array
8492
}
8593
$lines[] = sprintf('%s ====', $indent);
8694
$cases = $this->class->getEnumCases();
87-
$lines[] = implode(sprintf("\r\n%s ----\r\n", $indent), array_map(function (PhpEnumCase $x) use($indent) {
95+
$lines[] = implode(sprintf("\r\n%s ----\r\n", $indent), array_map(function (PhpEnumCase $x) use ($indent) {
8896
$doc = $x->getDocString();
8997
if (empty($doc)) {
9098
return sprintf('%s %s', $indent, $x->getName());

src/Php/Doc/PhpDocComment.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ public function getDescription(): string
3030
$str = $this->text;
3131
$str = str_replace(["\r\n", "\r", "\n"], "\n", $str);
3232
$lines = explode("\n", $str);
33-
return array_shift($lines);
33+
$firstLine = array_shift($lines);
34+
return preg_replace('/\@\S+.*/', '', $firstLine);
3435
}
3536

3637
public function getVarTypeName(): string {

src/Php/PhpTypeExpression.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace Smeghead\PhpClassDiagram\Php;
66

7-
use PhpParser\Comment\Doc;
87
use PhpParser\Node\Identifier;
98
use PhpParser\Node\Name;
109
use PhpParser\Node\Name\FullyQualified;
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use PHPUnit\Framework\TestCase;
6+
7+
use Smeghead\PhpClassDiagram\Config\Options;
8+
use Smeghead\PhpClassDiagram\DiagramElement\Entry;
9+
use Smeghead\PhpClassDiagram\DiagramElement\Relation;
10+
use Smeghead\PhpClassDiagram\Php\PhpReader;
11+
12+
final class ClassDiagramClassNameSummaryTest extends TestCase
13+
{
14+
private $fixtureDir;
15+
public function setUp(): void
16+
{
17+
$this->fixtureDir = sprintf('%s/fixtures', __DIR__);
18+
}
19+
20+
public function testClassnameWithSummary(): void
21+
{
22+
$options = new Options([
23+
'enable-class-name-summary' => true
24+
]);
25+
$directory = sprintf('%s/classname-summary', $this->fixtureDir);
26+
$filename = sprintf('%s/classname-summary/product/Product.php', $this->fixtureDir);
27+
$entries[] = new Entry('product', PhpReader::parseFile($directory, $filename, $options)[0]->getInfo(), $options);
28+
$filename = sprintf('%s/classname-summary/product/Price.php', $this->fixtureDir);
29+
$entries[] = new Entry('product', PhpReader::parseFile($directory, $filename, $options)[0]->getInfo(), $options);
30+
$filename = sprintf('%s/classname-summary/product/Name.php', $this->fixtureDir);
31+
$entries[] = new Entry('product', PhpReader::parseFile($directory, $filename, $options)[0]->getInfo(), $options);
32+
33+
$rel = new Relation($entries, $options);
34+
$expected =<<<EOS
35+
@startuml class-diagram
36+
package product as product {
37+
class "Product\\n<b>製品</b>" as product_Product {
38+
-name : Name
39+
-price : Price
40+
+method1(param1)
41+
}
42+
class "Price\\n<b>価格</b>" as product_Price {
43+
-price : int
44+
}
45+
class "Name\\n<b>製品名</b>" as product_Name {
46+
-name : string
47+
}
48+
}
49+
product_Product ..> product_Name
50+
product_Product ..> product_Price
51+
product_Product ..> product_Product
52+
@enduml
53+
EOS;
54+
$this->assertSame($expected, implode(PHP_EOL, $rel->dump()), 'output PlantUML script.');
55+
}
56+
public function testClassnameWithoutSummary(): void
57+
{
58+
$options = new Options([
59+
'disable-class-name-summary' => true
60+
]);
61+
$directory = sprintf('%s/classname-summary', $this->fixtureDir);
62+
$filename = sprintf('%s/classname-summary/product/Product.php', $this->fixtureDir);
63+
$entries[] = new Entry('product', PhpReader::parseFile($directory, $filename, $options)[0]->getInfo(), $options);
64+
$filename = sprintf('%s/classname-summary/product/Price.php', $this->fixtureDir);
65+
$entries[] = new Entry('product', PhpReader::parseFile($directory, $filename, $options)[0]->getInfo(), $options);
66+
$filename = sprintf('%s/classname-summary/product/Name.php', $this->fixtureDir);
67+
$entries[] = new Entry('product', PhpReader::parseFile($directory, $filename, $options)[0]->getInfo(), $options);
68+
69+
$rel = new Relation($entries, $options);
70+
$expected =<<<EOS
71+
@startuml class-diagram
72+
package product as product {
73+
class "Product" as product_Product {
74+
-name : Name
75+
-price : Price
76+
+method1(param1)
77+
}
78+
class "Price" as product_Price {
79+
-price : int
80+
}
81+
class "Name" as product_Name {
82+
-name : string
83+
}
84+
}
85+
product_Product ..> product_Name
86+
product_Product ..> product_Price
87+
product_Product ..> product_Product
88+
@enduml
89+
EOS;
90+
$this->assertSame($expected, implode(PHP_EOL, $rel->dump()), 'output PlantUML script.');
91+
}
92+
93+
}

test/OptionsTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,35 @@ public function testClassMethods3(): void {
8888

8989
$this->assertSame(true, $options->classMethods(), 'classMethods is default on.');
9090
}
91+
92+
public function testClassNameSummary1(): void {
93+
$opt = [
94+
'enable-class-name-summary' => true,
95+
];
96+
97+
$options = new Options($opt);
98+
99+
$this->assertSame(true, $options->classNameSummary(), 'classNameSummary is on.');
100+
}
101+
public function testClassNameSummary2(): void {
102+
$opt = [
103+
'disable-class-name-summary' => true,
104+
];
105+
106+
$options = new Options($opt);
107+
108+
$this->assertSame(false, $options->classNameSummary(), 'classNameSummary is off.');
109+
}
110+
public function testClassNameSummary3(): void {
111+
$opt = [
112+
];
113+
114+
$options = new Options($opt);
115+
116+
$this->assertSame(true, $options->classNameSummary(), 'classNameSummary is default on.');
117+
}
118+
119+
91120
public function testPhp1(): void {
92121
$opt = [
93122
'php7' => true,

test/PhpDocCommentTest.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
use PhpParser\ParserFactory;
44
use PHPUnit\Framework\TestCase;
55
use Smeghead\PhpClassDiagram\Php\Doc\PhpDocComment;
6-
use Smeghead\PhpClassDiagram\Php\PhpType;
7-
use Smeghead\PhpClassDiagram\Php\PhpTypeExpression;
86

97
final class PhpDocCommentTest extends TestCase {
108
private $fixtureDir;
@@ -120,4 +118,18 @@ public function test_getReturnType(): void {
120118

121119
$this->assertSame("int|null", $doc->getReturnTypeName(), 'return type name.');
122120
}
121+
public function test_getClassComment(): void {
122+
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
123+
$filename = sprintf('%s/php8/product/Product.php', $this->fixtureDir);
124+
try {
125+
$ast = $parser->parse(file_get_contents($filename));
126+
} catch (Error $error) {
127+
throw new \Exception("Parse error: {$error->getMessage()} file: {$filename}\n");
128+
}
129+
130+
$class = $ast[0]->stmts[2];
131+
$doc = new PhpDocComment($class);
132+
133+
$this->assertSame('', $doc->getDescription(), 'class type name.');
134+
}
123135
}

0 commit comments

Comments
 (0)