23
23
use phpDocumentor \Guides \Nodes \Node ;
24
24
use phpDocumentor \Guides \Nodes \SectionNode ;
25
25
use phpDocumentor \Guides \ReferenceResolvers \AnchorNormalizer ;
26
+ use Psr \Log \LoggerInterface ;
26
27
use SplStack ;
27
28
use Webmozart \Assert \Assert ;
28
29
30
+ use function sprintf ;
31
+
29
32
/** @implements NodeTransformer<DocumentNode|AnchorNode|SectionNode> */
30
33
final class CollectLinkTargetsTransformer implements NodeTransformer
31
34
{
@@ -34,6 +37,7 @@ final class CollectLinkTargetsTransformer implements NodeTransformer
34
37
35
38
public function __construct (
36
39
private readonly AnchorNormalizer $ anchorReducer ,
40
+ private LoggerInterface |null $ logger = null ,
37
41
) {
38
42
/*
39
43
* TODO: remove stack here, as we should not have sub documents in this way, sub documents are
@@ -68,17 +72,43 @@ public function enterNode(Node $node, CompilerContext $compilerContext): Node
68
72
$ currentDocument = $ this ->documentStack ->top ();
69
73
Assert::notNull ($ currentDocument );
70
74
$ anchor = $ node ->getId ();
71
- $ compilerContext ->getProjectNode ()->addLinkTarget (
72
- $ anchor ,
73
- new InternalTarget (
74
- $ currentDocument ->getFilePath (),
75
+ if ($ compilerContext ->getProjectNode ()->hasInternalTarget ($ anchor , $ node ->getLinkType ())) {
76
+ $ this ->logger ?->warning(
77
+ sprintf (
78
+ 'Duplicate anchor "%s" for link type "%s" in document "%s". The anchor is already used at "%s" ' ,
79
+ $ anchor ,
80
+ $ node ->getLinkType (),
81
+ $ compilerContext ->getDocumentNode ()->getFilePath (),
82
+ $ compilerContext ->getProjectNode ()->getInternalTarget ($ anchor , $ node ->getLinkType ())?->getDocumentPath(),
83
+ ),
84
+ $ compilerContext ->getLoggerInformation (),
85
+ );
86
+ } else {
87
+ $ compilerContext ->getProjectNode ()->addLinkTarget (
75
88
$ anchor ,
76
- $ node ->getLinkText (),
77
- $ node ->getLinkType (),
78
- ),
79
- );
89
+ new InternalTarget (
90
+ $ currentDocument ->getFilePath (),
91
+ $ anchor ,
92
+ $ node ->getLinkText (),
93
+ $ node ->getLinkType (),
94
+ ),
95
+ );
96
+ }
80
97
if ($ node instanceof MultipleLinkTargetsNode) {
81
98
foreach ($ node ->getAdditionalIds () as $ id ) {
99
+ if ($ compilerContext ->getProjectNode ()->hasInternalTarget ($ id , $ node ->getLinkType ())) {
100
+ $ this ->logger ?->warning(
101
+ sprintf (
102
+ 'Duplicate anchor "%s" for link type "%s" in document "%s". The anchor is already used at "%s" ' ,
103
+ $ anchor ,
104
+ $ node ->getLinkType (),
105
+ $ compilerContext ->getDocumentNode ()->getFilePath (),
106
+ $ compilerContext ->getProjectNode ()->getInternalTarget ($ anchor , $ node ->getLinkType ())?->getDocumentPath(),
107
+ ),
108
+ $ compilerContext ->getLoggerInformation (),
109
+ );
110
+ }
111
+
82
112
$ compilerContext ->getProjectNode ()->addLinkTarget (
83
113
$ id ,
84
114
new InternalTarget (
0 commit comments