Skip to content

Commit

Permalink
Merge pull request #69 from davelopez/improve_document_detection
Browse files Browse the repository at this point in the history
Improve document detection
  • Loading branch information
davelopez authored Jun 10, 2024
2 parents a492a62 + 866a8a6 commit b494829
Show file tree
Hide file tree
Showing 16 changed files with 333 additions and 71 deletions.
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@
"args": [
"--disable-extensions",
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/client/out/e2e/suite/index"
"--extensionTestsPath=${workspaceFolder}/client/out/tests/e2e/suite/index"
],
"outFiles": ["${workspaceFolder}client/out/e2e/**/*.js"],
"outFiles": ["${workspaceFolder}client/out/tests/e2e/**/*.js"],
"preLaunchTask": {
"type": "npm",
"script": "test-compile"
Expand Down
78 changes: 77 additions & 1 deletion client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@
"vscode": "^1.63.0"
},
"dependencies": {
"vscode-languageclient": "^8.1.0"
"vscode-languageclient": "^8.1.0",
"vscode-uri": "^3.0.8"
},
"scripts": {
"webpack": "webpack",
"watch": "webpack --watch --progress",
"test": "jest"
},
"devDependencies": {
"@types/glob": "^8.1.0"
}
}
5 changes: 5 additions & 0 deletions client/src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ export class ComparableWorkflow {
uri: Uri;
ref?: string;

constructor(uri: Uri, ref?: string) {
this.uri = uri;
this.ref = ref;
}

// TODO: This is no longer working until a new API is available
// ref: https://github.com/microsoft/vscode/issues/177319
// ref: https://github.com/microsoft/vscode/issues/84297
Expand Down
98 changes: 66 additions & 32 deletions client/src/common/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { OutputChannel, Uri, workspace } from "vscode";
import { workspace } from "vscode";
import { URI } from "vscode-uri";

/**
* Determines if the current workspace contains
Expand All @@ -22,8 +23,8 @@ export function getWorkspaceScheme(): "file" | "vscode-vfs" {
* @param targetScheme The new scheme.
* @returns A new copy of the URI with the new scheme.
*/
export function replaceUriScheme(uri: Uri, targetScheme: string): Uri {
return Uri.parse(uri.toString().replace(uri.scheme, targetScheme));
export function replaceUriScheme(uri: URI, targetScheme: string): URI {
return URI.parse(uri.toString().replace(uri.scheme, targetScheme));
}

/**
Expand All @@ -32,44 +33,77 @@ export function replaceUriScheme(uri: Uri, targetScheme: string): Uri {
* @param ref The git ref to add to the URI query
* @returns The URI with a ref query value set
*/
export function addRefToUri(uri: Uri, ref: string): Uri {
return Uri.parse(uri.toString() + `?ref=${ref}`);
export function addRefToUri(uri: URI, ref: string): URI {
return URI.parse(uri.toString() + `?ref=${ref}`);
}

/** Just for debugging */
export function debugPrintCommandArgs(command: string, args: unknown[], outputChannel: OutputChannel): void {
outputChannel.appendLine(`Command ${command} args:`);
for (let index = 0; index < args.length; index++) {
const element = args[index];
outputChannel.appendLine(` [${index}] ${JSON.stringify(element)}`);
}
outputChannel.appendLine(`---\n`);
// Workflow tests document can end with -test.yml, -tests.yml, -test.yaml, -tests.yaml
const workflowTestsDocumentPattern = /(.*)-(test|tests)\.(yml|yaml)$/;

// Workflow format1 documents can end with .ga
// Workflow format2 documents can end with .gxwf.yml or .gxwf.yaml
const format1WorkflowDocumentPattern = /\.ga$/;
const format2WorkflowDocumentPattern = /\.gxwf\.(yml|yaml)$/;

export function isWorkflowTestsDocument(uri: URI): boolean {
return workflowTestsDocumentPattern.test(uri.path);
}

export function isNativeWorkflowDocument(uri: URI): boolean {
return format1WorkflowDocumentPattern.test(uri.path);
}

export function isWorkflowTestsDocument(uri: Uri): boolean {
return uri.path.endsWith("-test.yml") || uri.path.endsWith("-tests.yml");
export function isFormat2WorkflowDocument(uri: URI): boolean {
return format2WorkflowDocumentPattern.test(uri.path);
}

export async function getAssociatedWorkflowUriFromTestsUri(workflowTestsDocumentUri: URI): Promise<URI | undefined> {
if (!isWorkflowTestsDocument(workflowTestsDocumentUri)) {
return undefined;
}

//Try to find a format1 workflow document first
let workflowDocumentUri = replaceUriPattern(workflowTestsDocumentUri, workflowTestsDocumentPattern, ".ga");
if (await fileUriExistsInWorkspace(workflowDocumentUri)) {
return workflowDocumentUri;
}
//Try to find a format2 workflow document
workflowDocumentUri = replaceUriPattern(workflowTestsDocumentUri, workflowTestsDocumentPattern, ".gxwf.yaml");
if (await fileUriExistsInWorkspace(workflowDocumentUri)) {
return workflowDocumentUri;
}

workflowDocumentUri = replaceUriPattern(workflowTestsDocumentUri, workflowTestsDocumentPattern, ".gxwf.yml");
if (await fileUriExistsInWorkspace(workflowDocumentUri)) {
return workflowDocumentUri;
}
return undefined;
}

export function isNativeWorkflowDocument(uri: Uri): boolean {
return uri.path.endsWith(".ga");
/**
* Replaces the matched pattern in the URI path with the replacement.
* @param uri The URI to be modified.
* @param pattern The pattern to match in the URI path.
* @param replacement The replacement string.
* @returns A new copy of the URI with the pattern replaced.
*/
export function replaceUriPattern(uri: URI, pattern: RegExp, replacement: string): URI {
const uriString = uri.toString();
const newUriString = uriString.replace(pattern, `$1${replacement}`);
const result = URI.parse(newUriString);
return result;
}

export async function getAssociatedWorkflowUriFromTestsUri(workflowTestsDocumentUri: Uri): Promise<Uri | undefined> {
const format2WorkflowUri = Uri.parse(
workflowTestsDocumentUri.toString().replace("-test.yml", ".gxwf.yml").replace("-tests.yml", ".gxwf.yml")
);
/**
* Determines if a file exists at the given URI in the workspace.
* @param uri The URI to check for existence.
* @returns true if the (virtual) file exists, false otherwise.
*/
export async function fileUriExistsInWorkspace(uri: URI): Promise<boolean> {
try {
await workspace.fs.stat(format2WorkflowUri);
return format2WorkflowUri;
await workspace.fs.stat(uri);
return true;
} catch {
const nativeWorkflowUri = Uri.parse(
workflowTestsDocumentUri.toString().replace("-test.yml", ".ga").replace("-tests.yml", ".ga")
);
try {
await workspace.fs.stat(nativeWorkflowUri);
return nativeWorkflowUri;
} catch {
return undefined;
}
return false;
}
}
25 changes: 19 additions & 6 deletions client/src/requests/gxworkflows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,43 @@ import {
TargetWorkflowDocumentParams,
} from "../languageTypes";

const TEST_DOCUMENT_TO_WORKFLOW_DOCUMENT_URI_MAP = new Map<string, Uri>();

export function setupRequests(
context: ExtensionContext,
nativeWorkflowClient: BaseLanguageClient,
gxFormat2Client: BaseLanguageClient
): void {
function createRequestHandler<TResult>(requestIdentifier: string) {
return async (params: TargetWorkflowDocumentParams) => {
let targetUri: Uri | undefined = Uri.parse(params.uri);
const targetUri: Uri | undefined = Uri.parse(params.uri);
let resultUri: Uri | undefined = undefined;
if (isWorkflowTestsDocument(targetUri)) {
// If the target is a test file, we need to find the associated workflow file
targetUri = await getAssociatedWorkflowUriFromTestsUri(targetUri);
//Try cache first
const cacheKey = targetUri.toString();
if (TEST_DOCUMENT_TO_WORKFLOW_DOCUMENT_URI_MAP.has(cacheKey)) {
resultUri = TEST_DOCUMENT_TO_WORKFLOW_DOCUMENT_URI_MAP.get(cacheKey)!;
}
if (!resultUri) {
resultUri = await getAssociatedWorkflowUriFromTestsUri(targetUri);
if (resultUri) {
TEST_DOCUMENT_TO_WORKFLOW_DOCUMENT_URI_MAP.set(cacheKey, resultUri);
}
}
}
if (!targetUri) {
if (!resultUri) {
console.debug("No associated workflow file found for:", params.uri);
return undefined;
}
// Open the file to include it in the document cache
await workspace.openTextDocument(targetUri);
await workspace.openTextDocument(resultUri);

let languageClient = gxFormat2Client;
if (isNativeWorkflowDocument(targetUri)) {
if (isNativeWorkflowDocument(resultUri)) {
languageClient = nativeWorkflowClient;
}
const requestParams: TargetWorkflowDocumentParams = { uri: targetUri.toString() };
const requestParams: TargetWorkflowDocumentParams = { uri: resultUri.toString() };
const result = await languageClient.sendRequest<TResult>(requestIdentifier, requestParams);
return result;
};
Expand Down
2 changes: 1 addition & 1 deletion client/tests/e2e/runTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ async function main(): Promise<void> {
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, "../../../");
const extensionDevelopmentPath = path.resolve(__dirname, "../../../../");

// The path to test runner
// Passed to --extensionTestsPath
Expand Down
15 changes: 9 additions & 6 deletions client/tests/e2e/suite/extension.ga.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
import * as vscode from "vscode";
import * as path from "path";
import * as assert from "assert";
import { beforeEach } from "mocha";
import * as path from "path";
import * as vscode from "vscode";
import {
activateAndOpenInEditor,
getDocUri,
assertDiagnostics,
closeAllEditors,
getDocUri,
openDocument,
resetSettings,
sleep,
assertDiagnostics,
updateSettings,
resetSettings,
waitForDiagnostics,
} from "./helpers";

Expand All @@ -22,14 +22,17 @@ suite("Native (JSON) Workflows", () => {
test("Clean workflow command removes non-essential properties", async () => {
const dirtyDocUri = getDocUri(path.join("json", "clean", "wf_01_dirty.ga"));
const cleanDocUri = getDocUri(path.join("json", "clean", "wf_01_clean.ga"));
const { document } = await activateAndOpenInEditor(dirtyDocUri);
const editor = await activateAndOpenInEditor(dirtyDocUri);
const document = editor?.document;
assert.ok(document);
await sleep(500); // Wait for extension to fully activate... yes Windows CI I'm looking at you...
const dirtyDoc = document.getText();
await vscode.commands.executeCommand("galaxy-workflows.cleanWorkflow");
await sleep(500); // Wait for command to apply changes
const actualCleanJson = document.getText();
assert.notEqual(dirtyDoc, actualCleanJson);
const expectedCleanDocument = await openDocument(cleanDocUri);
assert.ok(expectedCleanDocument);
const expectedCleanJson = expectedCleanDocument.getText();
assert.strictEqual(actualCleanJson, expectedCleanJson);
});
Expand Down
Loading

0 comments on commit b494829

Please sign in to comment.