Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic lsp integration test to check language support #1236

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/BackgroundCompilation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import { WorkspaceContext } from "./WorkspaceContext";
import { TaskOperation } from "./tasks/TaskQueue";

export class BackgroundCompilation {
private waitingToRun = false;

constructor(private folderContext: FolderContext) {}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@

import * as assert from "assert";
import * as vscode from "vscode";
import { WorkspaceContext } from "../../src/WorkspaceContext";
import { testAssetUri } from "../fixtures";
import { waitForNoRunningTasks } from "../utilities";
import { Workbench } from "../../src/utilities/commands";
import { activateExtensionForTest, updateSettings } from "./utilities/testutilities";
import { WorkspaceContext } from "../../../src/WorkspaceContext";
import { testAssetUri } from "../../fixtures";
import { waitForNoRunningTasks } from "../../utilities";
import { Workbench } from "../../../src/utilities/commands";
import { activateExtensionForTest, updateSettings } from "../utilities/testutilities";

suite("BackgroundCompilation Test Suite", () => {
let workspaceContext: WorkspaceContext;
Expand All @@ -38,7 +38,7 @@ suite("BackgroundCompilation Test Suite", () => {
await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS);
});

test("build all on save @slow", async () => {
test("build all on save", async () => {
const taskPromise = new Promise<void>(res => {
vscode.tasks.onDidStartTask(e => {
const task = e.execution.task;
Expand All @@ -58,5 +58,5 @@ suite("BackgroundCompilation Test Suite", () => {
await vscode.workspace.save(uri);

await taskPromise;
}).timeout(120000);
}).timeout(2 * 60 * 1000);
});
116 changes: 116 additions & 0 deletions test/integration-tests/language/GotoDefinition.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the VS Code Swift open source project
//
// Copyright (c) 2024 the VS Code Swift project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of VS Code Swift project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import * as vscode from "vscode";
import * as langclient from "vscode-languageclient/node";
import { expect } from "chai";
import { LanguageClientManager } from "../../../src/sourcekit-lsp/LanguageClientManager";
import { WorkspaceContext } from "../../../src/WorkspaceContext";
import { testAssetUri } from "../../fixtures";
import { FolderContext } from "../../../src/FolderContext";
import { executeTaskAndWaitForResult, waitForNoRunningTasks } from "../../utilities";
import { SwiftTask } from "../../../src/tasks/SwiftTaskProvider";
import { activateExtensionForSuite, folderInRootWorkspace } from "../utilities/testutilities";

async function waitForClientState(
languageClientManager: LanguageClientManager,
expectedState: langclient.State
): Promise<langclient.State> {
let clientState = undefined;
while (clientState !== expectedState) {
clientState = await languageClientManager.useLanguageClient(async client => client.state);
console.warn("Language client is not ready yet. Retrying in 100 ms...");
await new Promise(resolve => setTimeout(resolve, 100));
}
return clientState;
}

suite("Integration, Basic Language Support with Sourcekit-lsp", function () {
this.timeout(60 * 1000);

let clientManager: LanguageClientManager;
let workspaceContext: WorkspaceContext;
let folderContext: FolderContext;
const uri = testAssetUri("defaultPackage/Sources/PackageExe/main.swift");
const expectedDefinitionUri = testAssetUri(
"defaultPackage/Sources/PackageLib/PackageLib.swift"
);
// Position of the symbol 'a' in main.swift
const position = new vscode.Position(2, 6);

activateExtensionForSuite({
async setup(ctx) {
workspaceContext = ctx;
// Wait for a clean starting point, and run the build task for the fixture
await waitForNoRunningTasks();
folderContext = await folderInRootWorkspace("defaultPackage", workspaceContext);
await workspaceContext.focusFolder(folderContext);

const tasks = await vscode.tasks.fetchTasks({ type: "swift" });
const buildTask = tasks.find(t => t.name === "Build All (defaultPackage)");
const { exitCode, output } = await executeTaskAndWaitForResult(buildTask as SwiftTask);
expect(exitCode, `${output}`).to.equal(0);

// Ensure lsp client is ready
clientManager = workspaceContext.languageClientManager;
const clientState = await waitForClientState(clientManager, langclient.State.Running);
expect(clientState).to.equals(langclient.State.Running);
},
});

test("Goto Definition", async function () {
// Focus on the file of interest
const editor = await vscode.window.showTextDocument(uri);
const document = editor.document;

// Position of the symbol 'a' in main.swift
const definitionLocations = await vscode.commands.executeCommand<vscode.Location[]>(
"vscode.executeDefinitionProvider",
document.uri,
position
);

expect(definitionLocations).to.have.lengthOf(1, "There should be one definition of 'a'.");

const definition = definitionLocations[0];

// Assert that the definition is in PackageLib.swift at line 0
expect(definition.uri.toString()).to.equal(expectedDefinitionUri.toString());
expect(definition.range.start.line).to.equal(0);
});

test("Find All References", async function () {
// Focus on the file of interest
const editor = await vscode.window.showTextDocument(uri);
const document = editor.document;

const referenceLocations = await vscode.commands.executeCommand<vscode.Location[]>(
"vscode.executeReferenceProvider",
document.uri,
position
);

// We expect 2 references - one in `main.swift` and one in `PackageLib.swift`
expect(referenceLocations).to.have.lengthOf(2, "There should be two references to 'a'.");

// Extract reference URIs and sort them to have a predictable order
const referenceUris = referenceLocations.map(ref => ref.uri.toString()).sort();
const expectedUris = [
uri.toString(), // Reference in main.swift
expectedDefinitionUri.toString(), // Reference in PackageLib.swift
].sort();

expect(referenceUris).to.deep.equal(expectedUris);
});
});
21 changes: 10 additions & 11 deletions test/integration-tests/tasks/SwiftTaskProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
createSwiftTask,
createBuildAllTask,
getBuildAllTask,
SwiftTask,
} from "../../../src/tasks/SwiftTaskProvider";
import { SwiftToolchain } from "../../../src/toolchain/toolchain";
import {
Expand Down Expand Up @@ -63,9 +64,9 @@ suite("SwiftTaskProvider Test Suite", () => {
{ cwd: workspaceFolder.uri, scope: vscode.TaskScope.Workspace },
toolchain
);
const { exitCode } = await executeTaskAndWaitForResult(task);
expect(exitCode).to.equal(0);
});
const { exitCode, output } = await executeTaskAndWaitForResult(task);
expect(exitCode, `${output}`).to.equal(0);
}).timeout(10000);

test("Exit code on failure", async () => {
const task = createSwiftTask(
Expand Down Expand Up @@ -95,9 +96,9 @@ suite("SwiftTaskProvider Test Suite", () => {
new Version(1, 2, 3)
)
);
const { exitCode } = await executeTaskAndWaitForResult(task);
expect(exitCode).to.not.equal(0);
});
const { exitCode, output } = await executeTaskAndWaitForResult(task);
expect(exitCode, `${output}`).to.not.equal(0);
}).timeout(10000);
});

suite("provideTasks", () => {
Expand All @@ -115,12 +116,10 @@ suite("SwiftTaskProvider Test Suite", () => {
.and.to.include("-Xswiftc -diagnostic-style=llvm");
});

test("executes @slow", async () => {
test("executes", async () => {
assert(task);
const exitPromise = waitForEndTaskProcess(task);
await vscode.tasks.executeTask(task);
const exitCode = await exitPromise;
expect(exitCode).to.equal(0);
const { exitCode, output } = await executeTaskAndWaitForResult(task as SwiftTask);
expect(exitCode, `${output}`).to.equal(0);
}).timeout(180000); // 3 minutes to build
});

Expand Down
Loading