@@ -18,20 +18,25 @@ import { CancellationToken, DocumentLink, DocumentLinkProvider, Range, TextDocum
1818import { parseYamlToCTreeItem } from '../../generic/tree-item-yaml-parser' ;
1919import { CTreeItem , ETreeItemKind , ITreeItem } from '../../generic/tree-item' ;
2020import type { SolutionManager } from '../solution-manager' ;
21+ import { getCmsisPackRoot } from '../../utils/path-utils' ;
2122
2223/**
23- * Provide links for file references in solution and project files.
24+ * Provide links for file references in solution, project, and layer files as well as for *.cbuild*.yml files.
25+ *
2426 */
2527export class ReferenceLinkProvider implements DocumentLinkProvider < DocumentLink > {
28+ private static readonly REFERENCE_ITEM_TAGS = [ 'file' , 'layer' , 'project' , 'script' , 'regions' ,
29+ 'solution' , 'csolution' , 'cbuild' , 'clayer' , 'cproject' ] ;
30+
2631 constructor (
2732 private readonly solutionManager : SolutionManager ,
33+ private readonly cbuildFile ?: boolean ,
2834 ) {
2935 }
3036
3137 public provideDocumentLinks ( textDocument : TextDocument , _token ?: CancellationToken ) : DocumentLink [ ] {
3238 try {
3339 const topItem = parseYamlToCTreeItem ( textDocument . getText ( ) , textDocument . fileName ) ;
34-
3540 return ( topItem ?. filterItems ( item => this . isReferenceFileItem ( item ) ) ?? [ ] ) ?. flatMap ( ( item ) : DocumentLink [ ] => {
3641 const documentLink = this . treeItemToDocumentLink ( item , textDocument ) ;
3742 return documentLink ? [ documentLink ] : [ ] ;
@@ -47,15 +52,28 @@ export class ReferenceLinkProvider implements DocumentLinkProvider<DocumentLink>
4752 }
4853
4954 protected isReferenceFileItem ( item : ITreeItem < CTreeItem > ) : item is CTreeItem {
55+ if ( ! item || item . getKind ( ) !== ETreeItemKind . Scalar || ! item . getText ( ) )
56+ return false ;
5057 const tag = item . getTag ( ) ;
51- return ! ! tag && this . getReferenceItemTags ( ) . includes ( tag ) ;
58+ if ( ! tag || ! this . getReferenceItemTags ( ) . includes ( tag ) ) {
59+ return false ;
60+ }
61+ // in case of cbuild-ids.yml we can only expand links under 'cbuilds' section
62+ if ( tag === 'clayer' && ! item . getParent ( 'cbuilds' ) ) {
63+ return false ;
64+ }
65+ // in case of cbuild-ids.yml 'project' under 'cbuilds' is just a name, not path
66+ if ( tag === 'project' && ! ! item . getParent ( 'cbuilds' ) ) {
67+ return false ;
68+ }
69+ return true ;
5270 }
5371
5472 protected getReferenceItemTags ( ) : string [ ] {
55- return [ 'file' , 'layer' , 'project' , 'script' , 'regions' ] ;
73+ return ReferenceLinkProvider . REFERENCE_ITEM_TAGS ;
5674 }
5775
58- private treeItemToDocumentLink ( item : ITreeItem < CTreeItem > | undefined , textDocument : TextDocument ) : DocumentLink | undefined {
76+ private treeItemToDocumentLink ( item : ITreeItem < CTreeItem > , textDocument : TextDocument ) : DocumentLink | undefined {
5977 const uri = this . getUriFromItem ( item ) ;
6078 if ( ! uri ) {
6179 return undefined ;
@@ -68,20 +86,23 @@ export class ReferenceLinkProvider implements DocumentLinkProvider<DocumentLink>
6886 }
6987
7088
71- private getUriFromItem ( item ?: ITreeItem < CTreeItem > ) : Uri | undefined {
72- if ( ! item || item . getKind ( ) !== ETreeItemKind . Scalar ) {
73- return undefined ;
74- }
89+ private getUriFromItem ( item : ITreeItem < CTreeItem > ) : Uri | undefined {
7590 let text = item . getText ( ) ;
7691 if ( ! text ) {
7792 return undefined ;
7893 }
79- const rpcData = this . solutionManager . getRpcData ( ) ;
80- const context = this . getItemContext ( item ) ;
81- if ( rpcData && context ) {
82- text = rpcData . expandString ( text , context ) ;
83- }
8494
95+ // generated files can contain references to files in packs directory
96+ if ( text . startsWith ( '${CMSIS_PACK_ROOT}' ) ) {
97+ return Uri . file ( text . replace ( '${CMSIS_PACK_ROOT}' , getCmsisPackRoot ( ) ) ) ;
98+ }
99+ if ( ! this . cbuildFile ) { // generated files have all sequences expanded
100+ const rpcData = this . solutionManager . getRpcData ( ) ;
101+ const context = this . getItemContext ( item ) ;
102+ if ( rpcData && context ) {
103+ text = rpcData . expandString ( text , context ) ;
104+ }
105+ }
85106 const resolvedPath = item . resolvePath ( text ) ;
86107 return resolvedPath ? Uri . file ( resolvedPath ) : undefined ;
87108 }
0 commit comments