Skip to content

Commit

Permalink
Merge pull request #7632 from dibarbet/sg_tests
Browse files Browse the repository at this point in the history
Add integration test for navigating to source generated file
  • Loading branch information
dibarbet authored Oct 7, 2024
2 parents 85ab08b + fa877b4 commit 1697eda
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
activateCSharpExtension,
closeAllEditorsAsync,
findRangeOfString,
navigate,
openFileInWorkspaceAsync,
testIfCSharp,
testIfDevKit,
Expand Down Expand Up @@ -286,31 +287,3 @@ describe(`Go To Definition Tests`, () => {
expect(vscode.window.activeTextEditor?.document.uri.path.toLowerCase()).toContain('symbolcache');
});
});

async function navigate(
originalPosition: vscode.Position,
definitionLocations: vscode.Location[],
expectedFileName: string
): Promise<void> {
const windowChanged = new Promise<void>((resolve, _) => {
vscode.window.onDidChangeActiveTextEditor((_e) => {
if (_e?.document.fileName.includes(expectedFileName)) {
resolve();
}
});
});

await vscode.commands.executeCommand(
'editor.action.goToLocations',
vscode.window.activeTextEditor!.document.uri,
originalPosition,
definitionLocations,
'goto',
'Failed to navigate'
);

// Navigation happens asynchronously when a different file is opened, so we need to wait for the window to change.
await windowChanged;

expect(vscode.window.activeTextEditor?.document.fileName).toContain(expectedFileName);
}
28 changes: 28 additions & 0 deletions test/lsptoolshost/integrationTests/integrationHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,34 @@ export async function getCodeLensesAsync(): Promise<vscode.CodeLens[]> {
});
}

export async function navigate(
originalPosition: vscode.Position,
definitionLocations: vscode.Location[],
expectedFileName: string
): Promise<void> {
const windowChanged = new Promise<void>((resolve, _) => {
vscode.window.onDidChangeActiveTextEditor((_e) => {
if (_e?.document.fileName.includes(expectedFileName)) {
resolve();
}
});
});

await vscode.commands.executeCommand(
'editor.action.goToLocations',
vscode.window.activeTextEditor!.document.uri,
originalPosition,
definitionLocations,
'goto',
'Failed to navigate'
);

// Navigation happens asynchronously when a different file is opened, so we need to wait for the window to change.
await windowChanged;

expect(vscode.window.activeTextEditor?.document.fileName).toContain(expectedFileName);
}

export function sortLocations(locations: vscode.Location[]): vscode.Location[] {
return locations.sort((a, b) => {
const uriCompare = a.uri.fsPath.localeCompare(b.uri.fsPath);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as path from 'path';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import {
activateCSharpExtension,
closeAllEditorsAsync,
navigate,
openFileInWorkspaceAsync,
sleep,
sortLocations,
} from './integrationHelpers';
import { beforeAll, beforeEach, afterAll, test, expect, afterEach, describe } from '@jest/globals';

describe(`Source Generator Tests`, () => {
beforeAll(async () => {
await activateCSharpExtension();
});

beforeEach(async () => {
await openFileInWorkspaceAsync(path.join('src', 'app', 'SourceGenerator.cs'));

// Unfortunately, due to the way source generators work we will not necessarily have the source generated files
// as soon as the project finishes loading. It may be using a partial compilation which has not run generators yet.
// So we have to wait here for a bit to ensure the source generated files are available.
// Once we have enabled balanced mode in the extension, we will have an explicit command to run generators which
// we can use here to force the generation instead of waiting.
// See https://github.com/dotnet/roslyn/issues/75152
await sleep(5000);
});

afterAll(async () => {
await testAssetWorkspace.cleanupWorkspace();
});

afterEach(async () => {
await closeAllEditorsAsync();
});

test('Navigates to reference in source generated file', async () => {
const requestPosition = new vscode.Position(14, 25);
const referencesList = <vscode.Location[]>(
await vscode.commands.executeCommand(
'vscode.executeReferenceProvider',
vscode.window.activeTextEditor!.document.uri,
requestPosition
)
);
expect(referencesList.length).toEqual(8);
const referencesInGeneratedFiles = sortLocations(
referencesList.filter((r) => r.uri.scheme === 'roslyn-source-generated')
);
expect(referencesInGeneratedFiles.length).toEqual(7);
const firstPath = referencesInGeneratedFiles[0].uri.path;
expect(firstPath).toEqual('/SourceGenerationContext.g.cs');

await navigate(requestPosition, referencesInGeneratedFiles, 'SourceGenerationContext.g.cs');
expect(vscode.window.activeTextEditor?.document.getText()).toContain('// <auto-generated/>');
expect(vscode.window.activeTextEditor?.document.getText()).toContain(
'internal partial class SourceGenerationContext'
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Text.Json.Serialization;

namespace SourceGeneration;

public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureCelsius { get; set; }
public string Summary { get; set; }
}

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(WeatherForecast))]
internal partial class SourceGenerationContext : JsonSerializerContext
{
}

0 comments on commit 1697eda

Please sign in to comment.