11import * as path from 'path' ;
2- import { QLPackDiscovery , QLPack } from './qlpack-discovery' ;
2+ import { QLPackDiscovery } from './qlpack-discovery' ;
33import { Discovery } from './discovery' ;
4- import { EventEmitter , Event , Uri , RelativePattern , WorkspaceFolder , env , workspace } from 'vscode' ;
4+ import { EventEmitter , Event , Uri , RelativePattern , WorkspaceFolder , env } from 'vscode' ;
55import { MultiFileSystemWatcher } from './vscode-utils/multi-file-system-watcher' ;
66import { CodeQLCliServer } from './cli' ;
77
@@ -29,9 +29,8 @@ export abstract class QLTestNode {
2929 * A directory containing one or more QL tests or other test directories.
3030 */
3131export class QLTestDirectory extends QLTestNode {
32- private _children : QLTestNode [ ] = [ ] ;
3332
34- constructor ( _path : string , _name : string ) {
33+ constructor ( _path : string , _name : string , private _children : QLTestNode [ ] = [ ] ) {
3534 super ( _path , _name ) ;
3635 }
3736
@@ -55,10 +54,23 @@ export class QLTestDirectory extends QLTestNode {
5554 }
5655
5756 public finish ( ) : void {
57+ // remove empty directories
58+ this . _children . filter ( child =>
59+ child instanceof QLTestFile || child . children . length > 0
60+ ) ;
5861 this . _children . sort ( ( a , b ) => a . name . localeCompare ( b . name , env . language ) ) ;
59- for ( const child of this . _children ) {
62+ this . _children . forEach ( ( child , i ) => {
6063 child . finish ( ) ;
61- }
64+ if ( child . children ?. length === 1 && child . children [ 0 ] instanceof QLTestDirectory ) {
65+ // collapse children
66+ const replacement = new QLTestDirectory (
67+ child . children [ 0 ] . path ,
68+ child . name + ' / ' + child . children [ 0 ] . name ,
69+ Array . from ( child . children [ 0 ] . children )
70+ ) ;
71+ this . _children [ i ] = replacement ;
72+ }
73+ } ) ;
6274 }
6375
6476 private createChildDirectory ( name : string ) : QLTestDirectory {
@@ -98,12 +110,12 @@ interface QLTestDiscoveryResults {
98110 /**
99111 * The root test directory for each QL pack that contains tests.
100112 */
101- testDirectories : QLTestDirectory [ ] ;
113+ testDirectory : QLTestDirectory | undefined ;
102114 /**
103115 * The list of file system paths to watch. If any of these paths changes, the discovery results
104116 * may be out of date.
105117 */
106- watchPaths : string [ ] ;
118+ watchPath : string ;
107119}
108120
109121/**
@@ -112,7 +124,7 @@ interface QLTestDiscoveryResults {
112124export class QLTestDiscovery extends Discovery < QLTestDiscoveryResults > {
113125 private readonly _onDidChangeTests = this . push ( new EventEmitter < void > ( ) ) ;
114126 private readonly watcher : MultiFileSystemWatcher = this . push ( new MultiFileSystemWatcher ( ) ) ;
115- private _testDirectories : QLTestDirectory [ ] = [ ] ;
127+ private _testDirectory : QLTestDirectory | undefined ;
116128
117129 constructor (
118130 private readonly qlPackDiscovery : QLPackDiscovery ,
@@ -128,12 +140,16 @@ export class QLTestDiscovery extends Discovery<QLTestDiscoveryResults> {
128140 /**
129141 * Event to be fired when the set of discovered tests may have changed.
130142 */
131- public get onDidChangeTests ( ) : Event < void > { return this . _onDidChangeTests . event ; }
143+ public get onDidChangeTests ( ) : Event < void > {
144+ return this . _onDidChangeTests . event ;
145+ }
132146
133147 /**
134148 * The root test directory for each QL pack that contains tests.
135149 */
136- public get testDirectories ( ) : QLTestDirectory [ ] { return this . _testDirectories ; }
150+ public get testDirectory ( ) : QLTestDirectory | undefined {
151+ return this . _testDirectory ;
152+ }
137153
138154 private handleDidChangeQLPacks ( ) : void {
139155 this . refresh ( ) ;
@@ -146,70 +162,43 @@ export class QLTestDiscovery extends Discovery<QLTestDiscoveryResults> {
146162 }
147163
148164 protected async discover ( ) : Promise < QLTestDiscoveryResults > {
149- const testDirectories : QLTestDirectory [ ] = [ ] ;
150- const watchPaths : string [ ] = [ ] ;
151- const qlPacks = this . qlPackDiscovery . qlPacks ;
152- for ( const qlPack of qlPacks ) {
153- //HACK: Assume that only QL packs whose name ends with '-tests' contain tests.
154- if ( this . isRelevantQlPack ( qlPack ) ) {
155- watchPaths . push ( qlPack . uri . fsPath ) ;
156- const testPackage = await this . discoverTests ( qlPack . uri . fsPath , qlPack . name ) ;
157- if ( testPackage !== undefined ) {
158- testDirectories . push ( testPackage ) ;
159- }
160- }
161- }
162-
163- return { testDirectories, watchPaths } ;
165+ return {
166+ testDirectory : await this . discoverTests ( ) ,
167+ watchPath : this . workspaceFolder . uri . fsPath
168+ } ;
164169 }
165170
166171 protected update ( results : QLTestDiscoveryResults ) : void {
167- this . _testDirectories = results . testDirectories ;
172+ this . _testDirectory = results . testDirectory ;
168173
169174 // Watch for changes to any `.ql` or `.qlref` file in any of the QL packs that contain tests.
170175 this . watcher . clear ( ) ;
171- results . watchPaths . forEach ( watchPath => {
172- this . watcher . addWatch ( new RelativePattern ( watchPath , '**/*.{ql,qlref}' ) ) ;
173- } ) ;
176+ this . watcher . addWatch ( new RelativePattern ( results . watchPath , '**/*.{ql,qlref}' ) ) ;
174177 this . _onDidChangeTests . fire ( ) ;
175178 }
176179
177- /**
178- * Only include qlpacks suffixed with '-tests' that are contained
179- * within the provided workspace folder.
180- */
181- private isRelevantQlPack ( qlPack : QLPack ) : boolean {
182- return qlPack . name . endsWith ( '-tests' )
183- && workspace . getWorkspaceFolder ( qlPack . uri ) ?. index === this . workspaceFolder . index ;
184- }
185-
186180 /**
187181 * Discover all QL tests in the specified directory and its subdirectories.
188- * @param fullPath The full path of the test directory.
189- * @param name The display name to use for the returned `TestDirectory` object.
190182 * @returns A `QLTestDirectory` object describing the contents of the directory, or `undefined` if
191183 * no tests were found.
192184 */
193- private async discoverTests ( fullPath : string , name : string ) : Promise < QLTestDirectory | undefined > {
185+ private async discoverTests ( ) : Promise < QLTestDirectory > {
186+ const fullPath = this . workspaceFolder . uri . fsPath ;
187+ const name = this . workspaceFolder . name ;
194188 const resolvedTests = ( await this . cliServer . resolveTests ( fullPath ) )
195189 . filter ( ( testPath ) => ! QLTestDiscovery . ignoreTestPath ( testPath ) ) ;
196190
197- if ( resolvedTests . length === 0 ) {
198- return undefined ;
191+ const rootDirectory = new QLTestDirectory ( fullPath , name ) ;
192+ for ( const testPath of resolvedTests ) {
193+ const relativePath = path . normalize ( path . relative ( fullPath , testPath ) ) ;
194+ const dirName = path . dirname ( relativePath ) ;
195+ const parentDirectory = rootDirectory . createDirectory ( dirName ) ;
196+ parentDirectory . addChild ( new QLTestFile ( testPath , path . basename ( testPath ) ) ) ;
199197 }
200- else {
201- const rootDirectory = new QLTestDirectory ( fullPath , name ) ;
202- for ( const testPath of resolvedTests ) {
203- const relativePath = path . normalize ( path . relative ( fullPath , testPath ) ) ;
204- const dirName = path . dirname ( relativePath ) ;
205- const parentDirectory = rootDirectory . createDirectory ( dirName ) ;
206- parentDirectory . addChild ( new QLTestFile ( testPath , path . basename ( testPath ) ) ) ;
207- }
208198
209- rootDirectory . finish ( ) ;
199+ rootDirectory . finish ( ) ;
210200
211- return rootDirectory ;
212- }
201+ return rootDirectory ;
213202 }
214203
215204 /**
0 commit comments