@@ -11,9 +11,20 @@ import { DownloadFileProvider } from './download-file-provider';
11
11
import { ISourceLocation } from './location-mapping' ;
12
12
import { properRelative } from './path' ;
13
13
14
- const exists = async ( file : string ) => {
14
+ const enum LinkType {
15
+ Command ,
16
+ URI ,
17
+ }
18
+
19
+ type CommandLink = { type : LinkType . Command ; command : string ; args : unknown [ ] } ;
20
+ type UriLink = { type : LinkType . URI ; uri : vscode . Uri ; isFile : boolean } ;
21
+ type Link = CommandLink | UriLink ;
22
+
23
+ const exists = async ( uristr : string ) => {
15
24
try {
16
- await vscode . workspace . fs . stat ( vscode . Uri . file ( file ) ) ;
25
+ const uri = parseLink ( uristr ) ;
26
+ if ( uri . type === LinkType . Command ) return true ;
27
+ await vscode . workspace . fs . stat ( uri . uri ) ;
17
28
return true ;
18
29
} catch {
19
30
return false ;
@@ -59,19 +70,28 @@ const showPosition = async (
59
70
await vscode . window . showTextDocument ( doc , { viewColumn, selection : new vscode . Range ( pos , pos ) } ) ;
60
71
} ;
61
72
73
+ const runCommand = ( link : CommandLink ) =>
74
+ vscode . commands . executeCommand ( link . command , ...link . args ) ;
75
+
62
76
const showPositionInFile = async (
63
77
rootPath : string | undefined ,
64
78
location : ISourceLocation ,
65
79
viewColumn ?: vscode . ViewColumn ,
66
- ) => {
80
+ ) : Promise < boolean > => {
67
81
const diskPaths = getCandidateDiskPaths ( rootPath , location . source ) ;
68
82
const foundPaths = await Promise . all ( diskPaths . map ( exists ) ) ;
69
83
const existingIndex = foundPaths . findIndex ( ok => ok ) ;
70
84
if ( existingIndex === - 1 ) {
71
85
return false ;
72
86
}
73
87
74
- const doc = await vscode . workspace . openTextDocument ( vscode . Uri . file ( diskPaths [ existingIndex ] ) ) ;
88
+ const resolvedLink = parseLink ( diskPaths [ existingIndex ] ) ;
89
+ if ( resolvedLink . type === LinkType . Command ) {
90
+ await runCommand ( resolvedLink ) ; // delegate finding the position to the command provider
91
+ return true ;
92
+ }
93
+
94
+ const doc = await vscode . workspace . openTextDocument ( resolvedLink . uri ) ;
75
95
await showPosition ( doc , location . lineNumber , location . columnNumber , viewColumn ) ;
76
96
return true ;
77
97
} ;
@@ -102,6 +122,23 @@ const showPositionInUrl = async (
102
122
await showPosition ( document , lineNumber + 1 , columnNumber + 1 , viewColumn ) ;
103
123
return true ;
104
124
} ;
125
+ /**
126
+ * Parses a link into a link object
127
+ * @param url
128
+ * @returns
129
+ */
130
+ const parseLink = ( link : string | undefined ) : Link => {
131
+ const matchCommand = link ?. match ( / ^ c o m m a n d : ( [ \w \. ] + ) (?: \? ( .* ) ) ? / ) ;
132
+ if ( matchCommand ) {
133
+ const [ command , rawArgs ] = matchCommand . slice ( 1 ) ;
134
+ const parsed = rawArgs ? JSON . parse ( decodeURIComponent ( rawArgs ) ) : [ ] ;
135
+ const args = Array . isArray ( parsed ) ? parsed : [ parsed ] ;
136
+ return { type : LinkType . Command , command, args } ;
137
+ }
138
+ if ( link ?. match ( / \w \w + : / ) )
139
+ return { type : LinkType . URI , uri : vscode . Uri . parse ( link || '' ) , isFile : false } ;
140
+ return { type : LinkType . URI , uri : vscode . Uri . file ( link || '' ) , isFile : true } ;
141
+ } ;
105
142
106
143
/**
107
144
* Gets possible locations for the source on the local disk.
@@ -111,8 +148,11 @@ export const getCandidateDiskPaths = (rootPath: string | undefined, source: Dap.
111
148
return [ ] ;
112
149
}
113
150
151
+ const uri = parseLink ( source . path ) ;
152
+
114
153
const locations = [ source . path ] ;
115
- if ( ! rootPath ) {
154
+ if ( ! rootPath || uri . type === LinkType . Command || ! uri . isFile ) {
155
+ // no resolution for commands and virtual filesystems
116
156
return locations ;
117
157
}
118
158
0 commit comments