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 {
@@ -96,14 +108,15 @@ export class QLTestFile extends QLTestNode {
96108 */
97109interface QLTestDiscoveryResults {
98110 /**
99- * The root test directory for each QL pack that contains tests .
111+ * A directory that contains one or more QL Tests, or other QLTestDirectories .
100112 */
101- testDirectories : QLTestDirectory [ ] ;
113+ testDirectory : QLTestDirectory | undefined ;
114+
102115 /**
103- * The list of file system paths to watch. If any of these paths changes, the discovery results
104- * may be out of date .
116+ * The file system path to a directory to watch. If any ql or qlref file changes in
117+ * this directory, then this signifies a change in tests .
105118 */
106- watchPaths : string [ ] ;
119+ watchPath : string ;
107120}
108121
109122/**
@@ -112,7 +125,7 @@ interface QLTestDiscoveryResults {
112125export class QLTestDiscovery extends Discovery < QLTestDiscoveryResults > {
113126 private readonly _onDidChangeTests = this . push ( new EventEmitter < void > ( ) ) ;
114127 private readonly watcher : MultiFileSystemWatcher = this . push ( new MultiFileSystemWatcher ( ) ) ;
115- private _testDirectories : QLTestDirectory [ ] = [ ] ;
128+ private _testDirectory : QLTestDirectory | undefined ;
116129
117130 constructor (
118131 private readonly qlPackDiscovery : QLPackDiscovery ,
@@ -128,12 +141,17 @@ export class QLTestDiscovery extends Discovery<QLTestDiscoveryResults> {
128141 /**
129142 * Event to be fired when the set of discovered tests may have changed.
130143 */
131- public get onDidChangeTests ( ) : Event < void > { return this . _onDidChangeTests . event ; }
144+ public get onDidChangeTests ( ) : Event < void > {
145+ return this . _onDidChangeTests . event ;
146+ }
132147
133148 /**
134- * The root test directory for each QL pack that contains tests.
149+ * The root directory. There is at least one test in this directory, or
150+ * in a subdirectory of this.
135151 */
136- public get testDirectories ( ) : QLTestDirectory [ ] { return this . _testDirectories ; }
152+ public get testDirectory ( ) : QLTestDirectory | undefined {
153+ return this . _testDirectory ;
154+ }
137155
138156 private handleDidChangeQLPacks ( ) : void {
139157 this . refresh ( ) ;
@@ -144,72 +162,49 @@ export class QLTestDiscovery extends Discovery<QLTestDiscoveryResults> {
144162 this . refresh ( ) ;
145163 }
146164 }
147-
165+ static cnt = 0 ;
148166 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 } ;
167+ const timer = 'testDirectory-' + this . workspaceFolder . uri . fsPath + '-' + QLTestDiscovery . cnt ++ ;
168+ console . time ( timer ) ;
169+ const testDirectory = await this . discoverTests ( ) ;
170+ console . timeEnd ( timer ) ;
171+ return {
172+ testDirectory,
173+ watchPath : this . workspaceFolder . uri . fsPath
174+ } ;
164175 }
165176
166177 protected update ( results : QLTestDiscoveryResults ) : void {
167- this . _testDirectories = results . testDirectories ;
178+ this . _testDirectory = results . testDirectory ;
168179
169180 // Watch for changes to any `.ql` or `.qlref` file in any of the QL packs that contain tests.
170181 this . watcher . clear ( ) ;
171- results . watchPaths . forEach ( watchPath => {
172- this . watcher . addWatch ( new RelativePattern ( watchPath , '**/*.{ql,qlref}' ) ) ;
173- } ) ;
182+ this . watcher . addWatch ( new RelativePattern ( results . watchPath , '**/*.{ql,qlref}' ) ) ;
174183 this . _onDidChangeTests . fire ( ) ;
175184 }
176185
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-
186186 /**
187187 * 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.
190188 * @returns A `QLTestDirectory` object describing the contents of the directory, or `undefined` if
191189 * no tests were found.
192190 */
193- private async discoverTests ( fullPath : string , name : string ) : Promise < QLTestDirectory | undefined > {
191+ private async discoverTests ( ) : Promise < QLTestDirectory > {
192+ const fullPath = this . workspaceFolder . uri . fsPath ;
193+ const name = this . workspaceFolder . name ;
194194 const resolvedTests = ( await this . cliServer . resolveTests ( fullPath ) )
195195 . filter ( ( testPath ) => ! QLTestDiscovery . ignoreTestPath ( testPath ) ) ;
196196
197- if ( resolvedTests . length === 0 ) {
198- return undefined ;
197+ const rootDirectory = new QLTestDirectory ( fullPath , name ) ;
198+ for ( const testPath of resolvedTests ) {
199+ const relativePath = path . normalize ( path . relative ( fullPath , testPath ) ) ;
200+ const dirName = path . dirname ( relativePath ) ;
201+ const parentDirectory = rootDirectory . createDirectory ( dirName ) ;
202+ parentDirectory . addChild ( new QLTestFile ( testPath , path . basename ( testPath ) ) ) ;
199203 }
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- }
208204
209- rootDirectory . finish ( ) ;
205+ rootDirectory . finish ( ) ;
210206
211- return rootDirectory ;
212- }
207+ return rootDirectory ;
213208 }
214209
215210 /**
0 commit comments