Skip to content

Fix up intermittently failing doc comment test #1720

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

Merged
merged 1 commit into from
Jul 17, 2025
Merged
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
12 changes: 6 additions & 6 deletions src/editor/CommentCompletion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ class DocCommentCompletionProvider implements vscode.CompletionItemProvider {
document: vscode.TextDocument,
position: vscode.Position
) {
if (!vscode.window.activeTextEditor) {
const editor = vscode.window.visibleTextEditors.find(
e => e.document.uri.toString() === document.uri.toString()
);
if (!editor || editor.document.isClosed) {
return;
}
// Fixes https://github.com/swiftlang/vscode-swift/issues/1648
Expand All @@ -72,7 +75,7 @@ class DocCommentCompletionProvider implements vscode.CompletionItemProvider {
? [lineText, lineText, ""]
: /^(\s*)\/\/\s(.+)/.exec(lineText);
if (match) {
await vscode.window.activeTextEditor.edit(
await editor.edit(
edit => {
edit.replace(
new vscode.Range(position.line, 0, position.line, match[0].length),
Expand All @@ -82,10 +85,7 @@ class DocCommentCompletionProvider implements vscode.CompletionItemProvider {
{ undoStopBefore: false, undoStopAfter: true }
);
const newPosition = new vscode.Position(position.line, match[1].length + 4);
vscode.window.activeTextEditor.selection = new vscode.Selection(
newPosition,
newPosition
);
editor.selection = new vscode.Selection(newPosition, newPosition);
}
}
}
Expand Down
99 changes: 19 additions & 80 deletions test/integration-tests/editor/CommentCompletion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,13 @@ import { CommentCompletionProviders } from "../../../src/editor/CommentCompletio
import { Workbench } from "../../../src/utilities/commands";

suite("CommentCompletion Test Suite", () => {
let document: vscode.TextDocument | undefined;
let provider: CommentCompletionProviders;

setup(() => {
provider = new CommentCompletionProviders();
});

teardown(async () => {
const editor = vscode.window.visibleTextEditors.find(
editor => editor.document === document
);

if (editor && document) {
await vscode.window.showTextDocument(document, editor.viewColumn);
await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS);
}

provider.dispose();
});
teardown(() => provider.dispose());

suite("Function Comment Completion", () => {
test("Completion on line that isn't a comment", async () => {
Expand Down Expand Up @@ -404,7 +392,13 @@ suite("CommentCompletion Test Suite", () => {
});
});

suite("Document Comment Completion", () => {
suite("Document Comment Completion", function () {
setup(function () {
if (process.platform === "linux") {
// Skip as these tests access the active test editor which will sometimes crash on Linux.
this.skip();
}
});
test("Should not provide completions on first line", async () => {
const { document, positions } = await openDocument(`1️⃣
public func foo() {}`);
Expand Down Expand Up @@ -439,32 +433,28 @@ suite("CommentCompletion Test Suite", () => {

test("Should continue a documentation comment block on new line", async () => {
const { document, positions } = await openDocument(`
/// aaa
1️⃣
public func foo() {}`);
/// aaa
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the indentation got changed here (although I guess it's fine if the linter doesn't complain?)

1️⃣
public func foo() {}`);

const position = positions["1️⃣"];
await provider.docCommentCompletion.provideCompletionItems(document, position);

const newLine = document.getText(
new vscode.Range(position, position.translate(0, 1000))
);
const newLine = document.lineAt(position.line).text;

assert.strictEqual(newLine, "/// ", "New line should continue the comment block");
});

test("Should continue a documentation comment when an existing comment line is split", async () => {
const { document, positions } = await openDocument(`
/// aaa
1️⃣// bbb
public func foo() {}`);
/// aaa
1️⃣// bbb
public func foo() {}`);

const position = positions["1️⃣"];
await provider.docCommentCompletion.provideCompletionItems(document, position);

const newLine = document.getText(
new vscode.Range(position, position.translate(0, 1000))
);
const newLine = document.lineAt(position.line).text;

assert.strictEqual(newLine, "/// bbb", "New line should continue the comment block");
});
Expand All @@ -484,7 +474,7 @@ suite("CommentCompletion Test Suite", () => {
});

test("Should handle case when no active text editor", async () => {
const { document, positions } = await openDocument(`
const { document: doc, positions } = await openDocument(`
/// aaa
1️⃣
public func foo() {}`);
Expand All @@ -495,10 +485,7 @@ suite("CommentCompletion Test Suite", () => {
await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS);

// This should not throw an error
const items = await provider.docCommentCompletion.provideCompletionItems(
document,
position
);
const items = await provider.docCommentCompletion.provideCompletionItems(doc, position);

assert.equal(
items,
Expand All @@ -507,50 +494,6 @@ suite("CommentCompletion Test Suite", () => {
);
});

test("Should specifically test continueExistingDocCommentBlock with no active editor", async () => {
const { document, positions } = await openDocument(`
/// aaa
1️⃣
public func foo() {}`);

const position = positions["1️⃣"];

// Close all editors to simulate no active text editor
await vscode.commands.executeCommand(Workbench.ACTION_CLOSEALLEDITORS);

// Store original activeTextEditor property
const originalActiveTextEditor = Object.getOwnPropertyDescriptor(
vscode.window,
"activeTextEditor"
);

// Mock the activeTextEditor to be null for the specific method call
Object.defineProperty(vscode.window, "activeTextEditor", {
get: () => null,
configurable: true,
});

try {
// Call the method directly to ensure the branch is covered
await provider.docCommentCompletion["continueExistingDocCommentBlock"](
document,
position
);

// If we get here, the method didn't throw an error, which is what we want
assert.ok(true, "Method should not throw when there's no active editor");
} finally {
// Restore the original activeTextEditor property
if (originalActiveTextEditor) {
Object.defineProperty(
vscode.window,
"activeTextEditor",
originalActiveTextEditor
);
}
}
});

test("Should handle when previous line has // but not ///", async () => {
const { document, positions } = await openDocument(`
// aaa
Expand Down Expand Up @@ -641,8 +584,7 @@ suite("CommentCompletion Test Suite", () => {
return;
}

const column = lines[line].indexOf(str);
return new vscode.Position(line, column);
return new vscode.Position(line, lines[line].indexOf(str));
}

let purgedContent = content;
Expand All @@ -669,9 +611,6 @@ suite("CommentCompletion Test Suite", () => {

await vscode.window.showTextDocument(doc);

// Save the document so we can clean it up when the test finishes
document = doc;

return { document: doc, positions };
}
});
10 changes: 10 additions & 0 deletions test/integration-tests/tasks/SwiftTaskProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ suite("SwiftTaskProvider Test Suite", () => {
test("includes product debug task", async () => {
const tasks = await vscode.tasks.fetchTasks({ type: "swift" });
const task = tasks.find(t => t.name === "Build Debug PackageExe (defaultPackage)");
expect(
task,
'expected to find a task named "Build Debug PackageExe (defaultPackage)", instead found ' +
tasks.map(t => t.name)
).to.not.be.undefined;
expect(task?.detail).to.include("swift build --product PackageExe");
});

Expand All @@ -151,6 +156,11 @@ suite("SwiftTaskProvider Test Suite", () => {
new vscode.CancellationTokenSource().token
);
const task = tasks.find(t => t.name === "Build Release PackageExe (defaultPackage)");
expect(
task,
'expected to find a task named "Build Release PackageExe (defaultPackage)", instead found ' +
tasks.map(t => t.name)
).to.not.be.undefined;
expect(task?.detail).to.include("swift build -c release --product PackageExe");
});

Expand Down