From a5aebe1854a15aa3fac0b3aa01c7e08799b01b02 Mon Sep 17 00:00:00 2001 From: Nir Haas Date: Sun, 3 Jul 2022 00:40:07 +0300 Subject: [PATCH 1/2] add support for multi-file test suite When evaluating whether a symbol is a document or not, check if testify was imported by any file of the directory (which is the go package). Fixes golang/vscode-go#1130 --- src/goTest/resolve.ts | 4 ++-- src/testUtils.ts | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/goTest/resolve.ts b/src/goTest/resolve.ts index b0966579e4..fe66a9485b 100644 --- a/src/goTest/resolve.ts +++ b/src/goTest/resolve.ts @@ -24,7 +24,7 @@ import { getCurrentGoPath } from '../util'; import { getGoConfig } from '../config'; import { dispose, disposeIfEmpty, FileSystem, GoTest, GoTestKind, findModuleName, isInTest, Workspace } from './utils'; import { walk, WalkStop } from './walk'; -import { importsTestify } from '../testUtils'; +import { isPackageTestify } from '../testUtils'; export type ProvideSymbols = (doc: TextDocument, token?: CancellationToken) => Thenable; @@ -205,7 +205,7 @@ export class GoTestResolver { const seen = new Set(); const item = await this.getFile(doc.uri); const symbols = await this.provideDocumentSymbols(doc); - const testify = importsTestify(symbols); + const testify = await isPackageTestify(this.provideDocumentSymbols, doc); for (const symbol of symbols) { await this.processSymbol(doc, item, seen, testify, symbol); } diff --git a/src/testUtils.ts b/src/testUtils.ts index 53228a58d9..5055669c87 100644 --- a/src/testUtils.ts +++ b/src/testUtils.ts @@ -10,6 +10,7 @@ import cp = require('child_process'); import path = require('path'); import util = require('util'); +import fs = require('fs'); import vscode = require('vscode'); import { applyCodeCoverageToAllEditors } from './goCover'; @@ -149,6 +150,8 @@ export async function getTestFunctions( token?: vscode.CancellationToken ): Promise { const documentSymbolProvider = GoDocumentSymbolProvider(goCtx, true); + + const testify = await isPackageTestify(documentSymbolProvider.provideDocumentSymbols, doc, token); const symbols = await documentSymbolProvider.provideDocumentSymbols(doc, token); if (!symbols || symbols.length === 0) { return; @@ -158,7 +161,6 @@ export async function getTestFunctions( return; } const children = symbol.children; - const testify = importsTestify(symbols); return children.filter( (sym) => (sym.kind === vscode.SymbolKind.Function || sym.kind === vscode.SymbolKind.Method) && @@ -586,6 +588,35 @@ export function cancelRunningTests(): Thenable { }); } +export type ProvideSymbols = ( + doc: vscode.TextDocument, + token?: vscode.CancellationToken +) => Thenable; + +/** + * Returns whether a file in the package imports testify. + */ +export async function isPackageTestify( + symbolsProvier: ProvideSymbols, + doc: vscode.TextDocument, + token?: vscode.CancellationToken | undefined +) { + const fsReaddir = util.promisify(fs.readdir); + + // Get all the package documents. + const packageDir = path.parse(doc.fileName).dir; + const packageFilenames = await fsReaddir(packageDir); + const packageDocs = await Promise.all( + packageFilenames.map((e) => path.join(packageDir, e)).map(vscode.workspace.openTextDocument) + ); + + // Parse the symbols of each document. + const docSymbols = await Promise.all(packageDocs.map((e) => symbolsProvier(e, token))); + + // One file is enough. + return docSymbols.some(importsTestify); +} + /** * Get the test target arguments. * @@ -640,7 +671,7 @@ function removeRunFlag(flags: string[]): void { } } -export function importsTestify(syms: vscode.DocumentSymbol[]): boolean { +function importsTestify(syms: vscode.DocumentSymbol[]): boolean { if (!syms || syms.length === 0 || !syms[0]) { return false; } From efc72ad317d4fc8fcb0bab3c033dc0cd1897401e Mon Sep 17 00:00:00 2001 From: Nir Haas Date: Thu, 7 Jul 2022 00:20:06 +0300 Subject: [PATCH 2/2] use gopls PackageImports instead of manually using fs --- src/goDocumentSymbols.ts | 2 +- src/goTest/resolve.ts | 4 ++-- src/testUtils.ts | 38 +++++--------------------------------- 3 files changed, 8 insertions(+), 36 deletions(-) diff --git a/src/goDocumentSymbols.ts b/src/goDocumentSymbols.ts index ef6959c699..5809237e8d 100644 --- a/src/goDocumentSymbols.ts +++ b/src/goDocumentSymbols.ts @@ -102,5 +102,5 @@ async function listImports( ] }; const resp = await languageClient?.sendRequest(ExecuteCommandRequest.type, params); - return resp.Imports; + return resp.PackageImports; } diff --git a/src/goTest/resolve.ts b/src/goTest/resolve.ts index fe66a9485b..b0966579e4 100644 --- a/src/goTest/resolve.ts +++ b/src/goTest/resolve.ts @@ -24,7 +24,7 @@ import { getCurrentGoPath } from '../util'; import { getGoConfig } from '../config'; import { dispose, disposeIfEmpty, FileSystem, GoTest, GoTestKind, findModuleName, isInTest, Workspace } from './utils'; import { walk, WalkStop } from './walk'; -import { isPackageTestify } from '../testUtils'; +import { importsTestify } from '../testUtils'; export type ProvideSymbols = (doc: TextDocument, token?: CancellationToken) => Thenable; @@ -205,7 +205,7 @@ export class GoTestResolver { const seen = new Set(); const item = await this.getFile(doc.uri); const symbols = await this.provideDocumentSymbols(doc); - const testify = await isPackageTestify(this.provideDocumentSymbols, doc); + const testify = importsTestify(symbols); for (const symbol of symbols) { await this.processSymbol(doc, item, seen, testify, symbol); } diff --git a/src/testUtils.ts b/src/testUtils.ts index 5055669c87..e9a43b5d94 100644 --- a/src/testUtils.ts +++ b/src/testUtils.ts @@ -10,7 +10,6 @@ import cp = require('child_process'); import path = require('path'); import util = require('util'); -import fs = require('fs'); import vscode = require('vscode'); import { applyCodeCoverageToAllEditors } from './goCover'; @@ -150,8 +149,6 @@ export async function getTestFunctions( token?: vscode.CancellationToken ): Promise { const documentSymbolProvider = GoDocumentSymbolProvider(goCtx, true); - - const testify = await isPackageTestify(documentSymbolProvider.provideDocumentSymbols, doc, token); const symbols = await documentSymbolProvider.provideDocumentSymbols(doc, token); if (!symbols || symbols.length === 0) { return; @@ -161,6 +158,10 @@ export async function getTestFunctions( return; } const children = symbol.children; + + // With gopls dymbol provider symbols, the symbols have the imports of all + // the package, so suite tests from all files will be found. + const testify = importsTestify(symbols); return children.filter( (sym) => (sym.kind === vscode.SymbolKind.Function || sym.kind === vscode.SymbolKind.Method) && @@ -588,35 +589,6 @@ export function cancelRunningTests(): Thenable { }); } -export type ProvideSymbols = ( - doc: vscode.TextDocument, - token?: vscode.CancellationToken -) => Thenable; - -/** - * Returns whether a file in the package imports testify. - */ -export async function isPackageTestify( - symbolsProvier: ProvideSymbols, - doc: vscode.TextDocument, - token?: vscode.CancellationToken | undefined -) { - const fsReaddir = util.promisify(fs.readdir); - - // Get all the package documents. - const packageDir = path.parse(doc.fileName).dir; - const packageFilenames = await fsReaddir(packageDir); - const packageDocs = await Promise.all( - packageFilenames.map((e) => path.join(packageDir, e)).map(vscode.workspace.openTextDocument) - ); - - // Parse the symbols of each document. - const docSymbols = await Promise.all(packageDocs.map((e) => symbolsProvier(e, token))); - - // One file is enough. - return docSymbols.some(importsTestify); -} - /** * Get the test target arguments. * @@ -671,7 +643,7 @@ function removeRunFlag(flags: string[]): void { } } -function importsTestify(syms: vscode.DocumentSymbol[]): boolean { +export function importsTestify(syms: vscode.DocumentSymbol[]): boolean { if (!syms || syms.length === 0 || !syms[0]) { return false; }