@@ -6,6 +6,7 @@ import { Directory } from "./Directory";
6
6
import { File } from "./File" ;
7
7
import { fireOtherStudioAction , OtherStudioAction } from "../../commands/studio" ;
8
8
import { StudioOpenDialog } from "../../queries" ;
9
+ import { redirectDotvscodeRoot } from "../../utils/index" ;
9
10
10
11
declare function setTimeout ( callback : ( ...args : any [ ] ) => void , ms : number , ...args : any [ ] ) : NodeJS . Timeout ;
11
12
@@ -61,29 +62,63 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
61
62
} else {
62
63
filter = "*.cls,*.inc,*.mac,*.int" ;
63
64
}
64
- const folder = csp ? ( uri . path . endsWith ( "/" ) ? uri . path : uri . path + "/" ) : uri . path . replace ( / \/ / g, "." ) ;
65
+ const folder = ! csp
66
+ ? uri . path . replace ( / \/ / g, "." )
67
+ : uri . path === "/"
68
+ ? ""
69
+ : uri . path . endsWith ( "/" )
70
+ ? uri . path
71
+ : uri . path + "/" ;
65
72
const spec = csp ? folder + filter : folder . length > 1 ? folder . slice ( 1 ) + "/" + filter : filter ;
66
73
const dir = "1" ;
67
74
const orderBy = "1" ;
68
75
const system = api . ns === "%SYS" ? "1" : "0" ;
69
76
const flat = query . flat && query . flat . length ? query . flat . toString ( ) : "0" ;
70
77
const notStudio = "0" ;
71
78
const generated = query . generated && query . generated . length ? query . generated . toString ( ) : "0" ;
79
+ // get all web apps that have a filepath (Studio dialog used below returns REST ones too)
80
+ const cspApps = csp ? await api . getCSPApps ( ) . then ( ( data ) => data . result . content || [ ] ) : [ ] ;
81
+ const cspSubfolderMap = new Map < string , vscode . FileType > ( ) ;
82
+ const prefix = folder === "" ? "/" : folder ;
83
+ for ( const app of cspApps ) {
84
+ if ( ( app + "/" ) . startsWith ( prefix ) ) {
85
+ const subfolder = app . slice ( prefix . length ) . split ( "/" ) [ 0 ] ;
86
+ if ( subfolder ) {
87
+ cspSubfolderMap . set ( subfolder , vscode . FileType . Directory ) ;
88
+ }
89
+ }
90
+ }
91
+ const cspSubfolders = Array . from ( cspSubfolderMap . entries ( ) ) ;
92
+ // Assemble the results
72
93
return api
73
94
. actionQuery ( sql , [ spec , dir , orderBy , system , flat , notStudio , generated ] )
74
95
. then ( ( data ) => data . result . content || [ ] )
75
- . then ( ( data ) =>
76
- data . map ( ( item : StudioOpenDialog ) => {
77
- const name = item . Name ;
78
- const fullName = folder === "" ? name : folder + "/" + name ;
79
- if ( item . Type === "10" || item . Type === "9" ) {
80
- parent . entries . set ( name , new Directory ( name , fullName ) ) ;
81
- return [ name , vscode . FileType . Directory ] ;
82
- } else {
83
- return [ name , vscode . FileType . File ] ;
84
- }
85
- } )
86
- )
96
+ . then ( ( data ) => {
97
+ const results = data
98
+ . filter ( ( item : StudioOpenDialog ) =>
99
+ item . Type === "10"
100
+ ? csp && ! item . Name . includes ( "/" ) // ignore web apps here because there may be REST ones
101
+ : item . Type === "9" // class package
102
+ ? ! csp
103
+ : csp
104
+ ? item . Type === "5" // web app file
105
+ : true
106
+ )
107
+ . map ( ( item : StudioOpenDialog ) => {
108
+ const name = item . Name ;
109
+ const fullName = folder === "" ? name : csp ? folder + name : folder + "/" + name ;
110
+ if ( item . Type === "10" || item . Type === "9" ) {
111
+ parent . entries . set ( name , new Directory ( name , fullName ) ) ;
112
+ return [ name , vscode . FileType . Directory ] ;
113
+ } else {
114
+ return [ name , vscode . FileType . File ] ;
115
+ }
116
+ } ) ;
117
+ if ( ! csp ) {
118
+ return results ;
119
+ }
120
+ return results . concat ( cspSubfolders ) ;
121
+ } )
87
122
. catch ( ( error ) => {
88
123
error && console . error ( error ) ;
89
124
} ) ;
@@ -138,7 +173,8 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
138
173
overwrite : boolean ;
139
174
}
140
175
) : void | Thenable < void > {
141
- if ( uri . path . match ( / \/ \. [ ^ / ] * \/ / ) ) {
176
+ uri = redirectDotvscodeRoot ( uri ) ;
177
+ if ( uri . path . startsWith ( "/." ) ) {
142
178
throw vscode . FileSystemError . NoPermissions ( "dot-folders not supported by server" ) ;
143
179
}
144
180
const { query } = url . parse ( decodeURIComponent ( uri . toString ( ) ) , true ) ;
@@ -235,14 +271,17 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
235
271
private async _lookup ( uri : vscode . Uri ) : Promise < Entry > {
236
272
const parts = uri . path . split ( "/" ) ;
237
273
let entry : Entry = this . root ;
238
- for ( const part of parts ) {
274
+ for ( let i = 0 ; i < parts . length ; i ++ ) {
275
+ const part = parts [ i ] ;
239
276
if ( ! part ) {
240
277
continue ;
241
278
}
242
279
let child : Entry | undefined ;
243
280
if ( entry instanceof Directory ) {
244
281
child = entry . entries . get ( part ) ;
245
- if ( ! part . includes ( "." ) ) {
282
+ // If the last element of path is dotted and is one we haven't already cached as a directory
283
+ // then it is assumed to be a file.
284
+ if ( ! part . includes ( "." ) || i + 1 < parts . length ) {
246
285
const fullName = entry . name === "" ? part : entry . fullName + "/" + part ;
247
286
child = new Directory ( part , fullName ) ;
248
287
entry . entries . set ( part , child ) ;
@@ -274,10 +313,11 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
274
313
275
314
// Fetch from server and cache it
276
315
private async _lookupAsFile ( uri : vscode . Uri ) : Promise < File > {
277
- // Reject attempts to access files in .-folders such as .vscode and .git
278
- if ( uri . path . match ( / \/ \. [ ^ / ] * \/ / ) ) {
279
- throw vscode . FileSystemError . FileNotFound ( "dot-folders not supported by server" ) ;
316
+ uri = redirectDotvscodeRoot ( uri ) ;
317
+ if ( uri . path . startsWith ( "/." ) ) {
318
+ throw vscode . FileSystemError . NoPermissions ( "dot-folders not supported by server" ) ;
280
319
}
320
+
281
321
const { query } = url . parse ( decodeURIComponent ( uri . toString ( ) ) , true ) ;
282
322
const csp = query . csp === "" || query . csp === "1" ;
283
323
const fileName = csp ? uri . path : uri . path . slice ( 1 ) . replace ( / \/ / g, "." ) ;
0 commit comments