@@ -106,6 +106,8 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget {
106106 protected _showReplaceButtons = false ;
107107 protected _replaceTerm = '' ;
108108 protected searchTerm = '' ;
109+ protected readonly outsideWorkspaceRootUri = 'Other files' ;
110+ protected hasOutsideWorkspaceResult = false ;
109111
110112 protected appliedDecorations = new Map < string , string [ ] > ( ) ;
111113
@@ -305,8 +307,12 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget {
305307 const matches = this . findMatches ( searchTerm , widget , searchOptions ) ;
306308 numberOfResults += matches . length ;
307309 const fileUri : string = widget . editor . uri . toString ( ) ;
308- const root : string = this . workspaceService . getWorkspaceRootUri ( widget . editor . uri ) ! . toString ( ) ;
309- searchResults . push ( { root, fileUri, matches } ) ;
310+ const root : string | undefined = this . workspaceService . getWorkspaceRootUri ( widget . editor . uri ) ?. toString ( ) ;
311+ searchResults . push ( {
312+ root : root ? root : this . outsideWorkspaceRootUri ,
313+ fileUri,
314+ matches
315+ } ) ;
310316 } ) ;
311317
312318 return {
@@ -324,7 +330,12 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget {
324330 return ;
325331 }
326332 const collapseValue : string = this . searchInWorkspacePreferences [ 'search.collapseResults' ] ;
327- const { path } = this . filenameAndPath ( result . root , result . fileUri ) ;
333+ let path : string ;
334+ if ( result . root === this . outsideWorkspaceRootUri ) {
335+ path = new URI ( result . fileUri ) . path . dir . toString ( ) ;
336+ } else {
337+ path = this . filenameAndPath ( result . root , result . fileUri ) . path ;
338+ }
328339 const tree = this . resultTree ;
329340 let rootFolderNode = tree . get ( result . root ) ;
330341 if ( ! rootFolderNode ) {
@@ -345,13 +356,37 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget {
345356 this . collapseFileNode ( fileNode , collapseValue ) ;
346357 }
347358
359+ /**
360+ * Handle when searching completed.
361+ */
362+ protected handleSearchCompleted ( cancelIndicator : CancellationTokenSource ) : void {
363+ cancelIndicator . cancel ( ) ;
364+ this . sortResultTree ( ) ;
365+ this . refreshModelChildren ( ) ;
366+ }
367+
368+ /**
369+ * Sort the result tree by URIs.
370+ */
371+ protected sortResultTree ( ) : void {
372+ // Sort the result map by folder URI.
373+ this . resultTree = new Map ( [ ...this . resultTree ]
374+ . sort ( ( a : [ string , SearchInWorkspaceRootFolderNode ] , b : [ string , SearchInWorkspaceRootFolderNode ] ) => this . compare ( a [ 1 ] . folderUri , b [ 1 ] . folderUri ) ) ) ;
375+ // Update the list of children nodes, sorting them by their file URI.
376+ Array . from ( this . resultTree . values ( ) )
377+ . forEach ( ( folder : SearchInWorkspaceRootFolderNode ) => {
378+ folder . children = folder . children . sort ( ( a : SearchInWorkspaceFileNode , b : SearchInWorkspaceFileNode ) => this . compare ( a . fileUri , b . fileUri ) ) ;
379+ } ) ;
380+ }
381+
348382 async search ( searchTerm : string , searchOptions : SearchInWorkspaceOptions ) : Promise < void > {
349383 this . searchTerm = searchTerm ;
350384 searchOptions = {
351385 ...searchOptions ,
352386 exclude : this . getExcludeGlobs ( searchOptions . exclude )
353387 } ;
354388 this . resultTree . clear ( ) ;
389+ this . hasOutsideWorkspaceResult = false ;
355390 if ( this . cancelIndicator ) {
356391 this . cancelIndicator . cancel ( ) ;
357392 }
@@ -373,8 +408,9 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget {
373408 } ) ;
374409
375410 // Collect search results for opened editors which otherwise may not be found by ripgrep (ex: dirty editors).
376- const { numberOfResults : monacoNumberOfResults , matches : monacoMatches } = this . searchInOpenEditors ( searchTerm , searchOptions ) ;
377- monacoMatches . forEach ( m => {
411+ const { numberOfResults, matches } = this . searchInOpenEditors ( searchTerm , searchOptions ) ;
412+ this . hasOutsideWorkspaceResult = matches . some ( m => m . root === this . outsideWorkspaceRootUri ) ;
413+ matches . forEach ( m => {
378414 this . appendToResultTree ( m ) ;
379415 // Exclude pattern beginning with './' works after the fix of #8469.
380416 const { name, path } = this . filenameAndPath ( m . root , m . fileUri ) ;
@@ -385,7 +421,7 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget {
385421
386422 // Reduce `maxResults` due to editor results.
387423 if ( searchOptions . maxResults ) {
388- searchOptions . maxResults -= monacoNumberOfResults ;
424+ searchOptions . maxResults -= numberOfResults ;
389425 }
390426
391427 // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -402,18 +438,11 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget {
402438 pendingRefreshTimeout = setTimeout ( ( ) => this . refreshModelChildren ( ) , 100 ) ;
403439 } ,
404440 onDone : ( ) => {
405- cancelIndicator . cancel ( ) ;
406- // Sort the result map by folder URI.
407- this . resultTree = new Map ( [ ...this . resultTree ]
408- . sort ( ( a : [ string , SearchInWorkspaceRootFolderNode ] , b : [ string , SearchInWorkspaceRootFolderNode ] ) => this . compare ( a [ 1 ] . folderUri , b [ 1 ] . folderUri ) ) ) ;
409- // Update the list of children nodes, sorting them by their file URI.
410- Array . from ( this . resultTree . values ( ) )
411- . forEach ( ( folder : SearchInWorkspaceRootFolderNode ) => {
412- folder . children = folder . children . sort ( ( a : SearchInWorkspaceFileNode , b : SearchInWorkspaceFileNode ) => this . compare ( a . fileUri , b . fileUri ) ) ;
413- } ) ;
414- this . refreshModelChildren ( ) ;
441+ this . handleSearchCompleted ( cancelIndicator ) ;
415442 }
416- } , searchOptions ) . catch ( ( ) => undefined ) ;
443+ } , searchOptions ) . catch ( ( ) => {
444+ this . handleSearchCompleted ( cancelIndicator ) ;
445+ } ) ;
417446 }
418447
419448 focusFirstResult ( ) : void {
@@ -491,7 +520,7 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget {
491520 expanded : true ,
492521 id : rootUri ,
493522 parent : this . model . root as SearchInWorkspaceRoot ,
494- visible : this . workspaceService . isMultiRootWorkspaceOpened
523+ visible : ( this . hasOutsideWorkspaceResult && this . workspaceService . opened ) || this . workspaceService . isMultiRootWorkspaceOpened
495524 } ;
496525 }
497526
@@ -740,9 +769,11 @@ export class SearchInWorkspaceResultTreeWidget extends TreeWidget {
740769 < span className = { 'file-name' } >
741770 { this . toNodeName ( node ) }
742771 </ span >
743- < span className = { 'file-path' } >
744- { node . path }
745- </ span >
772+ { node . path !== '/' + this . outsideWorkspaceRootUri &&
773+ < span className = { 'file-path' } >
774+ { node . path }
775+ </ span >
776+ }
746777 </ div >
747778 </ div >
748779 < span className = 'notification-count-container highlighted-count-container' >
0 commit comments