/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import assert from 'assert'; import { Intent } from '../../src/extension/common/constants'; import '../../src/extension/intents/node/allIntents'; import { ssuite, stest } from '../base/stest'; import { KnownDiagnosticProviders } from '../simulation/diagnosticProviders'; import { forInlineChatIntent, simulateInlineChatWithStrategy } from '../simulation/inlineChatSimulator'; import { assertLessDiagnosticsAsync, assertNoDiagnosticsAsync, getWorkspaceDiagnostics } from '../simulation/outcomeValidators'; import { assertConversationalOutcome, assertInlineEdit, assertNoOccurrence, assertOccursOnce, fromFixture, toFile } from '../simulation/stestUtil'; forInlineChatIntent((strategy, nonExtensionConfigurations, suffix) => { ssuite({ title: `fix${suffix}`, subtitle: 'ruff', location: 'inline' }, () => { stest({ description: `Ruff(E231) Missing whitespace after ':'`, language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/ruff/ruff_error_E231.py')], queries: [ { file: 'ruff_error_E231.py', selection: [5, 1, 5, 10], query: [ `/fix Missing whitespace after ':'`, `To fix the problem.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'ruff', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'ruff') } ] }); }); }); ssuite({ title: `fix${suffix}`, subtitle: 'TSC', location: 'inline' }, () => { stest({ description: 'Error 2322 - type undefined is not assignable to type', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2322.ts')], queries: [ { file: 'tsc_error_2322.ts', selection: [37, 10, 37, 10], query: [ `/fix Type 'RangeMapping[] | undefined' is not assignable to type 'RangeMapping[]'. `, ` Type 'undefined' is not assignable to type 'RangeMapping[]'.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: '22222 Error 2322 - type undefined is not assignable to type', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2322.ts')], queries: [ { file: 'tsc_error_2322.ts', selection: [37, 10, 37, 10], query: [ `/fix Type 'RangeMapping[] | undefined' is not assignable to type 'RangeMapping[]'. `, ` Type 'undefined' is not assignable to type 'RangeMapping[]'.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Error 1015 - parameter cannot have question mark and initializer, with corresponding diagnostics', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_1015.ts')], queries: [ { file: 'tsc_error_1015.ts', selection: [0, 24, 0, 24], query: `/fix Parameter cannot have question mark and initializer.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Error 1015 - parameter cannot have question mark and initializer, without corresponding diagnostics', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_1015.ts')], queries: [ { file: 'tsc_error_1015.ts', selection: [0, 24, 0, 24], query: `/fix Parameter cannot have question mark and initializer.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Error 2420 - incorrect interface implementation', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [ fromFixture('fixing/typescript/tsc_error_2420/file0.ts'), fromFixture('fixing/typescript/tsc_error_2420/file1.ts') ], queries: [ { file: 'file0.ts', selection: [2, 6, 2, 6], query: [ `/fix Class 'Far' incorrectly implements interface 'IFar'.`, ` Property 'foo' is missing in type 'Far' but required in type 'IFar'.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Error 2420 - incorrect interface implementation, with related information', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [ fromFixture('fixing/typescript/tsc_error_2420/file0.ts'), fromFixture('fixing/typescript/tsc_error_2420/file1.ts') ], queries: [ { file: 'file0.ts', selection: [2, 6, 9, 1], query: [ `/fix Class 'Far' incorrectly implements interface 'IFar'.`, ` Property 'foo' is missing in type 'Far' but required in type 'IFar'.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Error 2391 - function implementation is missing or not immediately following the declaration', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2391.ts')], queries: [ { file: 'tsc_error_2391.ts', selection: [6, 4, 6, 13], query: [ `/fix Function implementation is missing or not immediately following the declaration.`, `'function1', which lacks return-type annotation, implicitly has an 'any' return type.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Error 2454 - variable is used before being assigned', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2454.ts')], queries: [ { file: 'tsc_error_2454.ts', selection: [21, 6, 21, 24], query: `/fix Variable 'telemetryEventName' is used before being assigned.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Error 2339 - property does not exist on type 1', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2339_1.ts')], queries: [ { file: 'tsc_error_2339_1.ts', selection: [16, 21, 16, 29], query: `/fix Property 'response' does not exist on type 'DocContext'.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Error 2554 - expected m arguments, but got n.', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2554.ts')], queries: [ { file: 'tsc_error_2554.ts', selection: [8, 7, 8, 21], query: `/fix Expected 1 arguments, but got 0.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Error 2341 - property is private and only accessible within class', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2341.ts')], queries: [ { file: 'tsc_error_2341.ts', selection: [7, 8, 7, 10], query: `/fix Property 'hi' is private and only accessible within class 'Bar'.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Error 2355 - a function whose declared type is neither undefined, void, nor any must return a value.', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2355.ts')], queries: [ { file: 'tsc_error_2355.ts', selection: [2, 37, 2, 44], query: `/fix A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); // Inspired by case 55 in /fix dataset version 10 // The fix in nice_egg_479lg7cb9q was too big, it was not a minimal change, and it was incorrect stest({ description: 'Error 2339 - (AML-10-55) property does not exist on type 2', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2339_2.ts')], queries: [ { file: 'tsc_error_2339_2.ts', selection: [5, 8, 5, 8], query: `/fix Property 'send' does not exist on type 'AutoUpdater'.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); // Inspired by case 98 in /fix dataset version 10 // Copilot proposed an incorrect fix, it should have added an additional method, instead it added a catch statement stest({ description: 'Error 2339 - (AML-10-98) property does not exist on type 3', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2339_3.ts')], queries: [ { file: 'tsc_error_2339_3.ts', selection: [65, 11, 65, 11], query: `/fix Property 'send' does not exist on type 'IpcRendererWithCommands'.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); // Add a missing impor at the right place stest({ description: 'Error 2304 - can not find name', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [ fromFixture('fixing/typescript/tsc_error_2304/file0.ts'), fromFixture('fixing/typescript/tsc_error_2304/file1.ts') ], queries: [ { file: 'file0.ts', selection: [10, 26, 10, 26], query: `/fix Cannot find name 'readFileSync'.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => { await assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc'); if (outcome.type === 'inlineEdit') { const indexOfFsImport = outcome.fileContents.indexOf(`import { readFileSync } from 'fs';`); assert.ok(indexOfFsImport >= 0, 'contains readFileSync import'); const indexOfDeclare = outcome.fileContents.indexOf(`declare function`); assert.ok(indexOfFsImport < indexOfDeclare, 'is before declare function'); } } } ] }); }); stest({ description: 'Error 2304 - (AML-10-14) can not find module', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2304_1.ts')], queries: [ { file: 'tsc_error_2304_1.ts', selection: [25, 1, 25, 1], query: `/fix Cannot find name 'expect'.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => { assert.strictEqual(outcome.type, 'inlineEdit'); const diagnostics = await getWorkspaceDiagnostics(accessor, workspace, 'tsc'); const filtered = diagnostics.filter(d => d.code !== 2307 && d.code !== 2305); // filter module not found, module has not exported member assert.equal(filtered.length, 0, 'only module not found diagnostics'); } } ] }); }); stest({ description: 'Error 2307 - can not find module', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2307_can_not_find_module.ts')], queries: [ { file: 'tsc_error_2307_can_not_find_module.ts', selection: [0, 25, 0, 40], query: [ `/fix Cannot find module '@angular/core' or its corresponding type declarations..`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => { assertConversationalOutcome(outcome); const match = outcome.chatResponseMarkdown.match(/```(ps|bash)[.\n\r]*npm install.*@angular\/core/); assert.ok(match, 'contains npm install @angular/core'); } } ] }); }); // Inspired by case 64 of /fix dataset version 10 // The fix was not correct, it just added a new line and did not resolve the error stest({ description: 'Error 18047 - (AML-10-64) possibly null', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_18047.ts')], queries: [ { file: 'tsc_error_18047.ts', selection: [4, 4, 4, 4], query: `/fix 'measurementSpan' is possibly 'null'.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); // Inspired by case 23 of /fix dataset version 10 stest({ description: 'Error 7006 - (AML-10-23) implicitly has any type', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_7006.ts')], queries: [ { file: 'tsc_error_7006.ts', selection: [1, 53, 1, 53], query: `/fix Parameter 'data' implicitly has an 'any' type.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); // Inspired by case 1 of /fix dataset version 8 stest({ description: 'Error 18047 - (AML-8-1) property does not exist on type window', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2339_4.ts')], queries: [ { file: 'tsc_error_2339_4.ts', selection: [1, 12, 1, 12], query: `/fix Property 'lx' does not exist on type 'Window & typeof globalThis'.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); // Inspired by case 86 of /fix dataset version 10 stest({ description: 'Error 18048 - (AML-10-86) possibly undefined', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_18048.ts')], queries: [ { file: 'tsc_error_18048.ts', selection: [3, 20, 3, 20], query: `/fix 'poppedElement' is possibly 'undefined'`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); // Inspired by case 125 of /fix dataset version 8 stest({ description: 'Error 2304 - (AML-8-125) can not find name', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2304_2.ts')], queries: [ { file: 'tsc_error_2304_2.ts', selection: [7, 2, 7, 2], query: `/fix Cannot find name 'cy'.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => { if (outcome.type === 'conversational') { const match = outcome.chatResponseMarkdown.match(/```(ps|bash)[.\n\r]*npm install.*cypress/); assert.ok(match, 'contains npm install cypress'); } else if (outcome.type === 'inlineEdit') { const diagnostics = await getWorkspaceDiagnostics(accessor, workspace, 'tsc'); const filtered = diagnostics.filter(d => d.code !== 2307 && d.code !== 2305); // filter module not found, module has not exported member assert.equal(filtered.length, 0, 'only module not found diagnostics'); } else { assert.fail('unexpected outcome type'); } } } ] }); }); stest({ description: 'Error 2304 - (AML-8-125) can not find name 2', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2304_3.ts')], queries: [ { file: 'tsc_error_2304_3.ts', selection: [1, 10, 1, 10], query: `/fix Cannot find name 'promises'. Did you mean 'Promise'?.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); // Inspired by case 25 of /fix dataset version 10 // The fix was not correct, it just added a new line and did not resolve the error stest({ description: `Error 7053 - (AML-10-25) expression of type can't be used to index`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_7053.ts')], queries: [ { file: 'tsc_error_7053.ts', selection: [9, 2, 9, 2], query: [ `/fix Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ Pi: number; PiTimes2: number; PiOn2: number; PiOn4: number; E: number; }.`, ` No index signature with a parameter of type 'string' was found on type '{ Pi: number; PiTimes2: number; PiOn2: number; PiOn4: number; E: number; }'.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); // Inspired by case 31 in /fix dataset version 10 stest({ description: '(AML-10-31) Parameter data implicitly has an any type.', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_implicit_any.ts')], queries: [ { file: 'tsc_implicit_any.ts', selection: [7, 38, 7, 42], query: `/fix Parameter 'data' implicitly has an 'any' type`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => { await assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc'); } } ] }); }); stest({ description: 'declaration or statement expected', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_1128.ts')], queries: [ { file: 'tsc_error_1128.ts', selection: [8, 0, 8, 1], query: `/fix Declaration or statement expected.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => { await assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc'); } } ] }); }); stest({ description: 'left side of comma operator is unused', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2695.ts')], queries: [ { file: 'tsc_error_2695.ts', selection: [3, 9, 3, 10], query: `/fix Left side of comma operator is unused and has no side effects.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => { await assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc'); } } ] }); }); stest({ description: 'object is possibly undefined', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2532.ts')], queries: [ { file: 'tsc_error_2532.ts', selection: [2, 12, 2, 15], query: `/fix 'obj' is possibly 'undefined'.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => { await assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc'); } } ] }); }); stest({ description: 'duplicate identifier', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2300.ts')], queries: [ { file: 'tsc_error_2300.ts', selection: [1, 6, 1, 13], query: `/fix Duplicate identifier 'MyArray'.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => { await assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc'); } } ] }); }); stest({ description: 'Error 2802 - large file - Type Uint32Array can only be iterated through', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_large_onigscanner/tsc_error_2802.ts')], queries: [ { file: 'tsc_error_2802.ts', selection: [442, 16, 454, 10], query: `/fix Type 'Uint32Array' can only be iterated through when using the '--downlevelIteration' flag or with a '--target' of 'es2015' or higher.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => { if (outcome.type === 'conversational') { // change to tsconfig.json } else { await assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc'); } } } ] }); }); stest({ description: 'can not assign to parameter of type', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/tsc_error_2345.ts')], queries: [ { file: 'tsc_error_2345.ts', selection: [1, 22, 1, 31], query: `/fix Argument of type 'T' is not assignable to parameter of type 'object | null'.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => { await assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc'); } } ] }); }); stest({ description: 'Error 2345 - Last two arguments swapped', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { const files = [ fromFixture('fixing/typescript/tsc_error_2345_2/file0.ts'), fromFixture('fixing/typescript/tsc_error_2345_2/file1.ts'), fromFixture('fixing/typescript/tsc_error_2345_2/database_mock.ts') ]; return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files, queries: [ { file: 'file0.ts', selection: [3, 35, 3, 40], query: [ `/fix Argument of type 'boolean' is not assignable to parameter of type 'number'.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Error 2345 - Got boolean but expected options bag', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { const files = [ fromFixture('fixing/typescript/tsc_error_2345_3/file0.ts'), fromFixture('fixing/typescript/tsc_error_2345_3/database_mock.ts') ]; return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files, queries: [ { file: 'file0.ts', selection: [3, 41, 3, 46], query: [ `/fix Argument of type 'boolean' is not assignable to parameter of type '{ timeout?: number | undefined; loose: boolean; }'.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Error 2554 - Got two args but expected options bag', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [ fromFixture('fixing/typescript/tsc_error_2554/legacy_database.ts'), fromFixture('fixing/typescript/tsc_error_2554/file1.ts'), fromFixture('fixing/typescript/tsc_error_2554/database_mock.ts') ], queries: [ { file: 'legacy_database.ts', selection: [9, 37, 9, 42], query: `/fix Expected 1-2 arguments, but got 3.`, expectedIntent: Intent.Fix, diagnostics: 'tsc', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Issue 6571', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/inlineChatSimulator.ts')], queries: [ { file: 'inlineChatSimulator.ts', selection: [302, 16, 302, 27], query: `/fix Cannot find name 'startOffset'.`, diagnostics: 'tsc', expectedIntent: 'fix', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'tsc') } ] }); }); stest({ description: 'Issue #7300', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [toFile({ fileName: 'textureAtlasAllocator.test.ts', fileContents: `/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License. See License.txt in the project root for license information.\r\n *--------------------------------------------------------------------------------------------*/\r\n\r\nimport { deepStrictEqual, strictEqual } from 'assert';\r\nimport { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';\r\nimport { TextureAtlasShelfAllocator } from 'vs/editor/browser/view/gpu/atlas/textureAtlasAllocator';\r\nimport { ensureNonNullable } from 'vs/editor/browser/view/gpu/gpuUtils';\r\nimport type { IRasterizedGlyph } from 'vs/editor/browser/view/gpu/raster/glyphRasterizer';\r\n\r\nconst blackInt = 0x000000FF;\r\nconst blackArr = [0x00, 0x00, 0x00, 0xFF];\r\n\r\nconst pixel1x1 = createRasterizedGlyph(1, 1, [...blackArr]);\r\nconst pixel2x1 = createRasterizedGlyph(2, 1, [...blackArr, ...blackArr]);\r\nconst pixel1x2 = createRasterizedGlyph(1, 2, [...blackArr, ...blackArr]);\r\n\r\nfunction initAllocator(w: number, h: number): { canvas: OffscreenCanvas; ctx: OffscreenCanvasRenderingContext2D; allocator: TextureAtlasShelfAllocator } {\r\n\tconst canvas = new OffscreenCanvas(w, h);\r\n\tconst ctx = ensureNonNullable(canvas.getContext('2d'));\r\n\tconst allocator = new TextureAtlasShelfAllocator(canvas, ctx);\r\n\treturn { canvas, ctx, allocator };\r\n}\r\n\r\nfunction createRasterizedGlyph(w: number, h: number, data: ArrayLike): IRasterizedGlyph {\r\n\tstrictEqual(w * h * 4, data.length);\r\n\tconst source = new OffscreenCanvas(w, h);\r\n\tconst imageData = new ImageData(w, h);\r\n\timageData.data.set(data);\r\n\tensureNonNullable(source.getContext('2d')).putImageData(imageData, 0, 0);\r\n\treturn {\r\n\t\tsource,\r\n\t\tboundingBox: { top: 0, left: 0, bottom: h - 1, right: w - 1 },\r\n\t\toriginOffset: { x: 0, y: 0 },\r\n\t};\r\n}\r\n\r\nsuite('TextureAtlasShelfAllocator', () => {\r\n\tensureNoDisposablesAreLeakedInTestSuite();\r\n\r\n\tlet lastUniqueGlyph: string | undefined;\r\n\tfunction getUniqueGlyphId(): [string, number] {\r\n\t\tif (!lastUniqueGlyph) {\r\n\t\t\tlastUniqueGlyph = 'a';\r\n\t\t} else {\r\n\t\t\tlastUniqueGlyph = String.fromCharCode(lastUniqueGlyph.charCodeAt(0) + 1);\r\n\t\t}\r\n\t\treturn [lastUniqueGlyph, blackInt];\r\n\t}\r\n\r\n\tsuiteSetup(() => {\r\n\t\tlastUniqueGlyph = undefined;\r\n\t});\r\n\r\n\ttest('single allocation', () => {\r\n\t\tconst { allocator } = initAllocator(2, 2);\r\n\t\t// 1o\r\n\t\t// oo\r\n\t\tdeepStrictEqual(allocator.allocate(...getUniqueGlyphId(), pixel1x1), {\r\n\t\t\tindex: 0,\r\n\t\t\tx: 0, y: 0,\r\n\t\t\tw: 1, h: 1,\r\n\t\t\toriginOffsetX: 0, originOffsetY: 0,\r\n\t\t});\r\n\t});\r\n\ttest('wrapping', () => {\r\n\t\tconst { allocator } = initAllocator(5, 4);\r\n\t\t// 1oooo\r\n\t\t// ooooo\r\n\t\t// ooooo\r\n\t\t// ooooo\r\n\t\tdeepStrictEqual(allocator.allocate(...getUniqueGlyphId(), pixel1x1), {\r\n\t\t\tindex: 0,\r\n\t\t\tx: 0, y: 0,\r\n\t\t\tw: 1, h: 1,\r\n\t\t\toriginOffsetX: 0, originOffsetY: 0,\r\n\t\t});\r\n\t\t// 12ooo\r\n\t\t// o2ooo\r\n\t\t// ooooo\r\n\t\t// ooooo\r\n\t\tdeepStrictEqual(allocator.allocate(...getUniqueGlyphId(), pixel1x2), {\r\n\t\t\tindex: 1,\r\n\t\t\tx: 1, y: 0,\r\n\t\t\tw: 1, h: 2,\r\n\t\t\toriginOffsetX: 0, originOffsetY: 0,\r\n\t\t});\r\n\t\t// 1233o\r\n\t\t// o2ooo\r\n\t\t// ooooo\r\n\t\t// ooooo\r\n\t\tdeepStrictEqual(allocator.allocate(...getUniqueGlyphId(), pixel2x1), {\r\n\t\t\tindex: 2,\r\n\t\t\tx: 2, y: 0,\r\n\t\t\tw: 2, h: 1,\r\n\t\t\toriginOffsetX: 0, originOffsetY: 0,\r\n\t\t});\r\n\t\t// 1233x\r\n\t\t// x2xxx\r\n\t\t// 44ooo\r\n\t\t// ooooo\r\n\t\tdeepStrictEqual(allocator.allocate(...getUniqueGlyphId(), pixel2x1), {\r\n\t\t\tindex: 3,\r\n\t\t\tx: 0, y: 2,\r\n\t\t\tw: 2, h: 1,\r\n\t\t\toriginOffsetX: 0, originOffsetY: 0,\r\n\t\t}, 'should wrap to next line as there\\'s no room left');\r\n\t\t// 1233x\r\n\t\t// x2xxx\r\n\t\t// 4455o\r\n\t\t// ooooo\r\n\t\tdeepStrictEqual(allocator.allocate(...getUniqueGlyphId(), pixel2x1), {\r\n\t\t\tindex: 4,\r\n\t\t\tx: 2, y: 2,\r\n\t\t\tw: 2, h: 1,\r\n\t\t\toriginOffsetX: 0, originOffsetY: 0,\r\n\t\t});\r\n\t\t// 1233x\r\n\t\t// x2xxx\r\n\t\t// 44556\r\n\t\t// ooooo\r\n\t\tdeepStrictEqual(allocator.allocate(...getUniqueGlyphId(), pixel1x1), {\r\n\t\t\tindex: 5,\r\n\t\t\tx: 4, y: 2,\r\n\t\t\tw: 1, h: 1,\r\n\t\t\toriginOffsetX: 0, originOffsetY: 0,\r\n\t\t});\r\n\t\t// 1233x\r\n\t\t// x2xxx\r\n\t\t// 44556\r\n\t\t// 7oooo\r\n\t\tdeepStrictEqual(allocator.allocate(...getUniqueGlyphId(), pixel1x1), {\r\n\t\t\tindex: 6,\r\n\t\t\tx: 0, y: 3,\r\n\t\t\tw: 1, h: 1,\r\n\t\t\toriginOffsetX: 0, originOffsetY: 0,\r\n\t\t}, 'should wrap to next line as there\\'s no room left');\r\n\t});\r\n\ttest('full', () => {\r\n\t\tconst { allocator } = initAllocator(3, 2);\r\n\t\t// 1oo\r\n\t\t// 1oo\r\n\t\tdeepStrictEqual(allocator.allocate(...getUniqueGlyphId(), pixel1x2), {\r\n\t\t\tindex: 0,\r\n\t\t\tx: 0, y: 0,\r\n\t\t\tw: 1, h: 2,\r\n\t\t\toriginOffsetX: 0, originOffsetY: 0,\r\n\t\t});\r\n\t\t// 122\r\n\t\t// 1oo\r\n\t\tdeepStrictEqual(allocator.allocate(...getUniqueGlyphId(), pixel2x1), {\r\n\t\t\tindex: 1,\r\n\t\t\tx: 1, y: 0,\r\n\t\t\tw: 2, h: 1,\r\n\t\t\toriginOffsetX: 0, originOffsetY: 0,\r\n\t\t});\r\n\t\tdeepStrictEqual(allocator.allocate(...getUniqueGlyphId(), pixel1x1), undefined, 'should return undefined when the canvas is full');\r\n\t});\r\n});\r\n\r\nsuite('TextureAtlasSlabAllocator', () => {\r\n\ttest('a', () => {\r\n\t});\r\n});\r\n` })], queries: [ { file: 'textureAtlasAllocator.test.ts', selection: [161, 0, 164, 2], query: '/fix Suites should include a call to `ensureNoDisposablesAreLeakedInTestSuite()` to ensure no disposables are leaked in tests.', diagnostics: 'tsc', expectedIntent: 'fix', validate: async (outcome, workspace, accessor) => { assertInlineEdit(outcome); await assertNoDiagnosticsAsync(accessor, outcome, workspace, KnownDiagnosticProviders.tscIgnoreImportErrors); } } ] }); }); }); ssuite({ title: `fix${suffix}`, subtitle: 'eslint', location: 'inline' }, () => { stest({ description: 'unexpected token', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_unexpected_token.ts')], queries: [ { file: 'eslint_unexpected_token.ts', selection: [14, 4, 14, 4], query: `/fix Parsing error: Expression expected.`, expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); // Inspired by case 52 of /fix dataset version 10 // The fix was not correct, it just added a new line and did not resolve the error stest({ description: '(AML-10-52) expected conditional expression', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_expected_conditional_expression.ts')], queries: [ { file: 'eslint_expected_conditional_expression.ts', selection: [8, 6, 8, 6], query: `/fix`, expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); // Inspired by case 1 in /fix dataset version 10 stest({ description: '(AML-10-1) do not access hasOwnProperty', language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_do_not_access_hasOwnProperty.ts')], queries: [ { file: 'eslint_do_not_access_hasOwnProperty.ts', selection: [9, 23, 9, 23], query: `/fix Do not access Object.prototype method 'hasOwnProperty' from target object.`, expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `comma expected`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_comma_expected.ts')], queries: [ { file: 'eslint_comma_expected.ts', selection: [8, 2, 8, 2], query: [ `/fix Parsing error: ',' expected.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); // Inspired by case 10 of /fix dataset version 17 stest({ description: `(AML-17-10) unexpected constant condition 1`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_unexpected_constant_condition_1.ts')], queries: [ { file: 'eslint_unexpected_constant_condition_1.ts', selection: [1, 4, 1, 4], query: [ `/fix Unexpected constant condition.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); // Inspired by case 152 of /fix dataset version 17 stest({ description: `(AML-17-152) unreachable code`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_unreachable_code.ts')], queries: [ { file: 'eslint_unreachable_code.ts', selection: [5, 3, 5, 3], query: [ `/fix Unreachable code.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); // Inspired by case 166 of /fix dataset version 17 stest({ description: `(AML-17-166) unexpected control character`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_unexpected_control_character.ts')], queries: [ { file: 'eslint_unexpected_control_character.ts', selection: [0, 11, 0, 11], query: [ `/fix Unexpected control character(s) in regular expression: \\x00.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); // Inspired by case 243 of /fix dataset version 17 stest({ description: `(AML-17-243) unexpected constant condition 2`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_unexpected_constant_condition_2.ts')], queries: [ { file: 'eslint_unexpected_constant_condition_2.ts', selection: [4, 9, 4, 9], query: [ `/fix Unexpected constant condition.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `class-methods-use-this with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_class_methods_use_this.ts')], queries: [ { file: 'eslint_class_methods_use_this.ts', selection: [14, 1, 14, 7], query: [ `/fix Expected 'this' to be used by class method 'append'.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `consistent-this with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_consistent_this.ts')], queries: [ { file: 'eslint_consistent_this.ts', selection: [8, 8, 8, 19], query: [ `/fix Unexpected alias 'self' for 'this'.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `constructor-super with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_constructor_super.ts')], queries: [ { file: 'eslint_constructor_super.ts', selection: [22, 1, 25, 2], query: [ `/fix Expected to call 'super()'.`, `Constructors for derived classes must contain a 'super' call.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `func-names with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_func_names.ts')], queries: [ { file: 'eslint_func_names.ts', selection: [4, 25, 4, 34], query: [ `/fix Unexpected unnamed function.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `func-style with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_func_style.ts')], queries: [ { file: 'eslint_func_style.ts', selection: [4, 7, 10, 1], query: [ `/fix Expected a function expression.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `max-lines-per-function with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_max_lines_per_function.ts')], queries: [ { file: 'eslint_max_lines_per_function.ts', selection: [4, 7, 58, 1], query: [ `/fix Function 'fastMark' has too many lines (55). Maximum allowed is 50.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `max-params with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_max_params.ts')], queries: [ { file: 'eslint_max_params.ts', selection: [10, 1, 10, 12], query: [ `/fix Constructor has too many parameters (5). Maximum allowed is 3.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `max-statements with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_max_statements.ts')], queries: [ { file: 'eslint_max_statements.ts', selection: [5, 7, 59, 1], query: [ `/fix Function 'fastMark' has too many statements (34). Maximum allowed is 10.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-case-declarations with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_case_declarations.ts')], queries: [ { file: 'eslint_no_case_declarations.ts', selection: [9, 3, 9, 61], query: [ `/fix Unexpected lexical declaration in case block.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-dupe-else-if with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_dupe_else_if.ts')], queries: [ { file: 'eslint_no_dupe_else_if.ts', selection: [11, 13, 11, 34], query: [ `/fix This branch can never execute. Its condition is a duplicate or covered by previous conditions in the if-else-if chain.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-duplicate-case with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_duplicate_case.ts')], queries: [ { file: 'eslint_no_duplicate_case.ts', selection: [20, 1, 21, 137], query: [ `/fix Please fix the problem at the location`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-duplicate-imports with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_duplicate_imports.ts')], queries: [ { file: 'eslint_no_duplicate_imports.ts', selection: [7, 0, 7, 55], query: [ `/fix './eslint_no_duplicate_case'' import is duplicated.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-fallthrough with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_fallthrough.ts')], queries: [ { file: 'eslint_no_fallthrough.ts', selection: [9, 2, 9, 9], query: [ `/fix Expected a 'break' statement before 'case'.`, `Constructors for derived classes must contain a 'super' call.` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-inner-declarations with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_inner_declarations.ts')], queries: [ { file: 'eslint_no_inner_declarations.ts', selection: [11, 2, 15, 3], query: [ `/fix Move function declaration to function body root.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-multi-assign with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_multi_assign.ts')], queries: [ { file: 'eslint_no_multi_assign.ts', selection: [10, 8, 10, 8], query: [ `/fix Unexpected chained assignment.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-negated-condition with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_negated_condition.ts')], queries: [ { file: 'eslint_no_negated_condition.ts', selection: [8, 8, 8, 53], query: [ `/fix Unexpected negated condition.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-negated-condition 2 with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_negated_condition_2.ts')], queries: [ { file: 'eslint_no_negated_condition_2.ts', selection: [6, 2, 11, 3], query: [ `/fix Unexpected negated condition.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-new with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_new.ts')], queries: [ { file: 'eslint_no_new.ts', selection: [38, 0, 38, 30], query: [ `/fix Please fix the problem at the location`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-sequences with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_sequences.ts')], queries: [ { file: 'eslint_no_sequences.ts', selection: [16, 26, 16, 27], query: [ `/fix Please fix the problem at the location`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-sparse-arrays with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_sparse_arrays.ts')], queries: [ { file: 'eslint_no_sparse_arrays.ts', selection: [4, 25, 4, 30], query: [ `/fix Unexpected comma in middle of array.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-sparse-arrays 2 with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_sparse_arrays_2.ts')], queries: [ { file: 'eslint_no_sparse_arrays_2.ts', selection: [4, 29, 4, 66], query: [ `/fix Unexpected comma in middle of array.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `no-sparse-arrays 3 with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_no_sparse_arrays_3.ts')], queries: [ { file: 'eslint_no_sparse_arrays_3.ts', selection: [4, 26, 4, 56], query: [ `/fix Unexpected comma in middle of array.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `require-await with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_require_await.ts')], queries: [ { file: 'eslint_require_await.ts', selection: [6, 7, 6, 32], query: [ `/fix Async function 'readConfig' has no 'await' expression.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: `sort-keys with cookbook`, language: 'typescript', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/typescript/eslint_sort_keys.ts')], queries: [ { file: 'eslint_sort_keys.ts', selection: [21, 2, 21, 10], query: [ `/fix Expected object keys to be in ascending order. 'extended' should be before 'value'.`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'eslint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'eslint') } ] }); }); stest({ description: 'Issue #7544', language: 'typescript', nonExtensionConfigurations }, (accessor) => { return simulateInlineChatWithStrategy(strategy, accessor, { files: [toFile({ filePath: fromFixture('fix/issue-7544/notebookMulticursor.ts') })], queries: [ { file: 'notebookMulticursor.ts', selection: [262, 41, 262, 41], query: 'fix the error', diagnostics: 'tsc', expectedIntent: 'fix', validate: async (outcome, workspace, accessor) => { assertInlineEdit(outcome); assertOccursOnce(outcome.fileContents, '\tundoRedo?: {\n\t\telements: IPastFutureElements;\n\t};'); } } ] }); }); }); ssuite({ title: `fix${suffix}`, subtitle: 'pylint', location: 'inline' }, () => { stest({ description: 'unecessary parenthesis', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pylint_unecessary_parenthesis.py')], queries: [ { file: 'pylint_unecessary_parenthesis.py', selection: [7, 0, 7, 0], query: `/fix Unnecessary parens after 'if' keyword`, expectedIntent: Intent.Fix, diagnostics: 'pylint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pylint') } ] }); }); stest({ description: 'unused module imported', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pylint_unused_import.py')], queries: [ { file: 'pylint_unused_import.py', selection: [0, 0, 0, 0], query: `/fix Unused Path imported from pathlib`, expectedIntent: Intent.Fix, diagnostics: 'pylint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pylint') } ] }); }); stest({ description: `line-too-long cookbook 1 function definition with long parameters`, language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pylint_line_too_long_1.py')], queries: [ { file: 'pylint_line_too_long_1.py', selection: [8, 0, 8, 2], query: [ `/fix`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'pylint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pylint') } ] }); }); stest({ description: `line-too-long cookbook 2 long print statememt`, language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pylint_line_too_long_2.py')], queries: [ { file: 'pylint_line_too_long_2.py', selection: [7, 0, 7, 0], query: [ `/fix`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'pylint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pylint') } ] }); }); stest({ description: `line-too-long cookbook 3 long dictionary / list`, language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pylint_line_too_long_3.py')], queries: [ { file: 'pylint_line_too_long_3.py', selection: [8, 0, 8, 0], query: [ `/fix`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'pylint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pylint') } ] }); }); stest({ description: `line-too-long cookbook 4 long if condition and function call`, language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pylint_line_too_long_4.py')], queries: [ { file: 'pylint_line_too_long_4.py', selection: [15, 0, 15, 2], query: [ `/fix`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'pylint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pylint') } ] }); }); stest({ description: `line-too-long cookbook 5 multi-line docstring`, language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pylint_line_too_long_5.py')], queries: [ { file: 'pylint_line_too_long_5.py', selection: [7, 8, 9, 8], query: [ `/fix`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'pylint', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pylint') } ] }); }); }); ssuite({ title: `fix${suffix}`, subtitle: 'pyright', location: 'inline' }, () => { stest({ description: 'cannot instantiate abstract class', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_no_abstract_class_instantiation.py')], queries: [ { file: 'pyright_no_abstract_class_instantiation.py', selection: [9, 4, 9, 4], query: `/fix Cannot instantiate abstract class "Base"\n "Base.foo" is abstract`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); stest({ description: 'all Annotated types should include at least two type arguments', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_annotated_types_missing_argument.py')], queries: [ { file: 'pyright_annotated_types_missing_argument.py', selection: [4, 3, 4, 3], query: `/fix Expected one type argument and one or more annotations for "Annotated"`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); stest({ description: 'should not generate an error for variables declared in outer scopes', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_assignment_scopes.py')], queries: [ { file: 'pyright_assignment_scopes.py', selection: [24, 8, 24, 8], query: `/fix "d" is not defined`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); stest({ description: 'async cannot be used in a non-async function', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_async_in_non_async_function.py')], queries: [ { file: 'pyright_async_in_non_async_function.py', selection: [17, 4, 17, 4], query: `/fix Use of "async" not allowed outside of async function`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); stest({ description: 'await cannot be used in a non-async function', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_await_in_non_async_function.py')], queries: [ { file: 'pyright_await_in_non_async_function.py', selection: [14, 0, 14, 0], query: `/fix "await" allowed only within async function`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); stest({ description: 'bad token', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_badtoken.py')], queries: [ { file: 'pyright_badtoken.py', selection: [4, 7, 4, 7], query: `/fix Invalid character in identifier`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); stest({ description: 'Bar does not define a do_something2 method', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_missing_method.py')], queries: [ { file: 'pyright_missing_method.py', selection: [28, 0, 28, 0], query: [ `/fix Cannot access member "do_something2" for type "Bar"`, ` Member "do_something2" is unknown` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); // Inspired by case 2 in /fix dataset version 10 // Copilot misunderstood the directive and did a non-null check on the wrong variable stest({ description: '(AML-10-2) can not be assigned 1', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_can_not_be_assigned_to_1.py')], queries: [ { file: 'pyright_can_not_be_assigned_to_1.py', selection: [13, 15, 13, 15], query: [ `/fix Expression of type "tuple[str | None, Path]" cannot be assigned to return type "Tuple[str, Path]`, ` Type "str | None" cannot be assigned to type "str"`, ` Type "None" cannot be assigned to type "str"`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertLessDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); // Inspired by case 15 in /fix dataset version 10 // The error was that Copilot was not able to localize exactly the code that is causing the error and it didn't provide any edit // This test has three times the error stest({ description: '(AML-10-15) object not subscriptable', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_object_not_subscriptable.py')], queries: [ { file: 'pyright_object_not_subscriptable.py', selection: [17, 8, 17, 8], query: `/fix Object of type "None" is not subscriptable`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertLessDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); // Inspired by case 35 of /fix dataset version 10 // In the AML run, copilot did not understand the error and did not fix it stest({ description: '(AML-10-35) can not access member', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_can_not_access_member.py')], queries: [ { file: 'pyright_can_not_access_member.py', selection: [2, 23, 2, 23], query: [ `/fix Cannot access member "includes" for type "set[Unknown]"`, ` Member "includes" is unknown` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); // Inspired by case 36 of /fix dataset version 10 // In the AML run, copilot did not understand the error and did not fix it stest({ description: '(AML-10-36) can not be assigned 2', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_can_not_be_assigned_to_2.py')], queries: [ { file: 'pyright_can_not_be_assigned_to_2.py', selection: [4, 19, 4, 19], query: `/fix Expression of type "list[None]" cannot be assigned to declared type "List[int] | None"`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); // Inspired by case 4 of /fix dataset version 10 // In the AML run, copilot did not understand the error and did not fix it stest({ description: '(AML-10-4) parameter already assigned', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_parameter_already_assigned.py')], queries: [ { file: 'pyright_parameter_already_assigned.py', selection: [7, 33, 7, 33], query: `/fix Parameter "input_shape" is already assigned`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); // Inspired by case 48 of /fix dataset version 10 // In the AML run, copilot did not understand the error and did not fix it stest({ description: '(AML-10-48) can not be assigned 3', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_can_not_be_assigned_to_3.py')], queries: [ { file: 'pyright_can_not_be_assigned_to_3.py', selection: [9, 14, 9, 14], query: [ `/fix Argument of type "dict[str, int]" cannot be assigned to parameter "platforms" of type "list[str] | str" in function "setup"`, ` Type "dict[str, int]" cannot be assigned to type "list[str] | str"`, ` "dict[str, int]" is incompatible with "list[str]"`, ` "dict[str, int]" is incompatible with "str"`, ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); // Inspired by case 58 of /fix dataset version 10 // The AML run has removed a big part of the code and replaced with non-minimal edits, this initial issue was not resolved stest({ description: '(AML-10-58) not defined', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_not_defined.py')], queries: [ { file: 'pyright_not_defined.py', selection: [7, 20, 7, 20], query: `/fix "T_Or" is not defined`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); // Inspired by case 29 of /fix dataset version 10 stest({ description: '(AML-10-29) instance of bool has no to_string member', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_no_to_string_member.py')], queries: [ { file: 'pyright_no_to_string_member.py', selection: [1, 19, 1, 19], query: `/fix`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); // Inspired by case 110 of /fix dataset version 8 stest({ description: '(AML-8-110) not defined', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_self_as_first_argument.py')], queries: [ { file: 'pyright_self_as_first_argument.py', selection: [7, 20, 7, 20], query: `/fix Instance methods should take a "self" parameter`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); // Inspired by case 73 of /fix dataset version 8 stest({ description: '(AML-8-73) no value for argument in function call', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_no_value_for_argument.py')], queries: [ { file: 'pyright_no_value_for_argument.py', selection: [12, 16, 12, 16], query: `/fix Argument missing for parameter "error_message"`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); stest({ description: 'undefined variable', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_undefined_variable.py')], queries: [ { file: 'pyright_undefined_variable.py', selection: [0, 0, 0, 4], query: `/fix "Play" is not defined`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); stest({ description: 'import missing', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_missing_import.py')], queries: [ { file: 'pyright_missing_import.py', selection: [3, 26, 3, 34], query: `/fix "unittest" is not defined`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); stest({ description: 'general type issue', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_general_type_issue.py')], queries: [ { file: 'pyright_general_type_issue.py', selection: [29, 22, 29, 25], query: [ `/fix Argument of type "Msg[Foo]" cannot be assigned to parameter "msg" of type "Msg[FooBar]" in function "handle"`, ` "Msg[Foo]" is incompatible with "Msg[FooBar]"`, ` Type parameter "T@Msg" is invariant, but "Foo" is not the same as "FooBar"` ].join('\n'), expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); stest({ description: 'optional member access', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_optional_member_access.py')], queries: [ { file: 'pyright_optional_member_access.py', selection: [12, 23, 12, 28], query: `/fix "upper" is not a known member of "None"`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); stest({ description: 'unbound variable', language: 'python', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/python/pyright_unbound_variable.py')], queries: [ { file: 'pyright_unbound_variable.py', selection: [4, 11, 4, 12], query: `/fix "a" is possibly unbound`, expectedIntent: Intent.Fix, diagnostics: 'pyright', validate: async (outcome, workspace, accessor) => assertNoDiagnosticsAsync(accessor, outcome, workspace, 'pyright') } ] }); }); }); ssuite({ title: `fix${suffix}`, subtitle: 'cpp', location: 'inline' }, () => { stest({ description: 'code fix for C++', language: 'cpp', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [ fromFixture('fixing/cpp/basic/main.cpp'), ], queries: [ { file: 'main.cpp', selection: [5, 32], query: '/fix too few arguments in function call', expectedIntent: Intent.Fix, diagnostics: 'cpp', validate: async (outcome, workspace, accessor) => { assert.strictEqual(outcome.type, 'inlineEdit'); assertNoOccurrence(outcome.fileContents, 'getName();'); await assertLessDiagnosticsAsync(accessor, outcome, workspace, 'cpp'); }, }, ], }); }); }); /** * This method validates the outcome by finding if after the edit, there remain errors */ ssuite({ title: `fix${suffix}`, subtitle: 'roslyn', location: 'inline' }, () => { // Inspired by case 28 of /fix dataset version 10 // Final edit does not correspond to fetched response stest({ description: '(AML-10-28) field is never used', language: 'csharp', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/csharp/roslyn_field_never_used.cs')], queries: [ { file: 'roslyn_field_never_used.cs', selection: [29, 37, 29, 37], query: `/fix "The event 'Class3.event3' is never used"`, expectedIntent: Intent.Fix, diagnostics: 'roslyn', validate: async (outcome, workspace, accessor) => assertLessDiagnosticsAsync(accessor, outcome, workspace, 'roslyn') } ] }); }); // Inspired by case 57 of /fix dataset version 10 stest({ description: '(AML-10-57) call is not awaited, execution continues', language: 'csharp', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/csharp/roslyn_call_not_awaited.cs')], queries: [ { file: 'roslyn_call_not_awaited.cs', selection: [5, 12, 5, 12], query: `/fix Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.`, expectedIntent: Intent.Fix, diagnostics: 'roslyn', validate: async (outcome, workspace, accessor) => assertLessDiagnosticsAsync(accessor, outcome, workspace, 'roslyn') } ] }); }); // Inspired by case 3523 of /fix dataset version 17 stest({ description: '(AML-17-3523) has same name as', language: 'csharp', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/csharp/roslyn_has_same_name_as.cs')], queries: [ { file: 'roslyn_has_same_name_as.cs', selection: [3, 23, 3, 24], query: `/fix Type parameter 'W' has the same name as the type parameter from outer type 'Class1.Class11'.`, expectedIntent: Intent.Fix, diagnostics: 'roslyn', validate: async (outcome, workspace, accessor) => assertLessDiagnosticsAsync(accessor, outcome, workspace, 'roslyn') } ] }); }); stest({ description: 'does not exist', language: 'csharp', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/csharp/roslyn_does_not_exist.cs')], queries: [ { file: 'roslyn_does_not_exist.cs', selection: [3, 26, 3, 32], query: `/fix The name 'mesage' does not exist in the current context`, expectedIntent: Intent.Fix, diagnostics: 'roslyn', validate: async (outcome, workspace, accessor) => assertLessDiagnosticsAsync(accessor, outcome, workspace, 'roslyn') } ] }); }); stest({ description: 'does not contain a definition', language: 'csharp', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/csharp/roslyn_does_not_contain_definition_for.cs')], queries: [ { file: 'roslyn_does_not_contain_definition_for.cs', selection: [4, 23, 4, 28], query: `/fix 'C' does not contain a definition for 'Field'`, expectedIntent: Intent.Fix, diagnostics: 'roslyn', validate: async (outcome, workspace, accessor) => assertLessDiagnosticsAsync(accessor, outcome, workspace, 'roslyn') } ] }); }); stest({ description: 'no argument given', language: 'csharp', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/csharp/roslyn_no_argument_given.cs')], queries: [ { file: 'roslyn_no_argument_given.cs', selection: [6, 19, 6, 20], query: `/fix There is no argument given that corresponds to the required parameter 'count' of 'C.C(int)'`, expectedIntent: Intent.Fix, diagnostics: 'roslyn', validate: async (outcome, workspace, accessor) => assertLessDiagnosticsAsync(accessor, outcome, workspace, 'roslyn') } ] }); }); stest({ description: 'missing using directive', language: 'csharp', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/csharp/roslyn_missing_using_directive.cs')], queries: [ { file: 'roslyn_missing_using_directive.cs', selection: [2, 5, 2, 16], query: `/fix The type or namespace name 'ConditionalAttribute' could not be found (are you missing a using directive or an assembly reference?)`, expectedIntent: Intent.Fix, diagnostics: 'roslyn', validate: async (outcome, workspace, accessor) => assertLessDiagnosticsAsync(accessor, outcome, workspace, 'roslyn') } ] }); }); stest({ description: 'semi-colon expected', language: 'csharp', nonExtensionConfigurations }, (testingServiceCollection) => { return simulateInlineChatWithStrategy(strategy, testingServiceCollection, { files: [fromFixture('fixing/csharp/roslyn_semi_colon_expected.cs')], queries: [ { file: 'roslyn_semi_colon_expected.cs', selection: [4, 11, 4, 11], query: `/fix ; expected`, expectedIntent: Intent.Fix, diagnostics: 'roslyn', validate: async (outcome, workspace, accessor) => assertLessDiagnosticsAsync(accessor, outcome, workspace, 'roslyn') } ] }); }); }); ssuite({ title: `fix${suffix}`, subtitle: 'powershell', location: 'inline' }, () => { stest({ description: 'Issue #7894', language: 'powershell', nonExtensionConfigurations }, (accessor) => { return simulateInlineChatWithStrategy(strategy, accessor, { files: [toFile({ filePath: fromFixture('fix/issue-7894/shellIntegration.ps1') })], queries: [ { file: 'shellIntegration.ps1', selection: [175, 0, 175, 3], query: '[psscriptanalyzer:Error]: MissingEndCurlyBrace: MissingEndCurlyBrace (in fix/issue-7894/shellIntegration.ps1)', expectedIntent: 'fix', validate: async (outcome, workspace) => { assertInlineEdit(outcome); const newText = outcome.appliedEdits.map(e => e.newText).join(''); assert.strictEqual(newText.includes('param'), true); } } ] }); }); }); });