Skip to content

Commit 02711d7

Browse files
Fix check error handling and output formatting
1 parent 95c93ef commit 02711d7

File tree

7 files changed

+260
-46
lines changed

7 files changed

+260
-46
lines changed

workspaces/ballerina/ballerina-core/src/rpc-types/ai-panel/interfaces.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ export interface ProjectImports {
119119
// Data-mapper related interfaces
120120
export interface MetadataWithAttachments {
121121
metadata: ExtendedDataMapperMetadata;
122-
attachments?: Attachment[];
122+
attachments: Attachment[];
123123
}
124124

125125
export interface InlineMappingsSourceResult {

workspaces/ballerina/ballerina-extension/src/features/ai/dataMapping.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { PackageInfo, TypesGenerationResult } from "./service/datamapper/types";
3333
import { URI } from "vscode-uri";
3434
import { getAllDataMapperSource } from "./service/datamapper/datamapper";
3535
import { StateMachine } from "../../stateMachine";
36+
import { CopilotEventHandler } from "./service/event";
3637

3738
// Set to false to include mappings with default values
3839
const OMIT_DEFAULT_MAPPINGS_ENABLED = true;
@@ -473,13 +474,15 @@ export async function createTempFileAndGenerateMetadata(params: CreateTempFileRe
473474

474475
export async function generateMappings(
475476
metadataWithAttachments: MetadataWithAttachments,
476-
context: any
477+
context: any,
478+
eventHandler: CopilotEventHandler
477479
): Promise<AllDataMapperSourceRequest> {
478480
const targetFilePath = metadataWithAttachments.metadata.codeData.lineRange.fileName || context.documentUri;
479481

480482
const generatedMappings = await generateMappingExpressionsFromModel(
481483
metadataWithAttachments.metadata.mappingsModel as DMModel,
482-
metadataWithAttachments.attachments || []
484+
metadataWithAttachments.attachments || [],
485+
eventHandler
483486
);
484487

485488
const customFunctionMappings = generatedMappings.filter(mapping => mapping.isFunctionCall);
@@ -1060,6 +1063,7 @@ export async function generateInlineMappingsSource(
10601063
inlineMappingRequest: MetadataWithAttachments,
10611064
langClient: ExtendedLangClient,
10621065
context: any,
1066+
eventHandler: CopilotEventHandler
10631067
): Promise<InlineMappingsSourceResult> {
10641068
if (!inlineMappingRequest) {
10651069
throw new Error("Inline mapping request is required");
@@ -1096,16 +1100,18 @@ export async function generateInlineMappingsSource(
10961100

10971101
// Prepare mapping request payload
10981102
const mappingRequestPayload: MetadataWithAttachments = {
1099-
metadata: tempFileMetadata
1103+
metadata: tempFileMetadata,
1104+
attachments: []
11001105
};
1101-
if (inlineMappingRequest.attachments && inlineMappingRequest.attachments.length > 0) {
1106+
if (inlineMappingRequest.attachments.length > 0) {
11021107
mappingRequestPayload.attachments = inlineMappingRequest.attachments;
11031108
}
11041109

11051110
// Generate mappings and source code
11061111
const allMappingsRequest = await generateMappings(
11071112
mappingRequestPayload,
1108-
context
1113+
context,
1114+
eventHandler
11091115
);
11101116

11111117
const generatedSourceResponse = await getAllDataMapperSource(allMappingsRequest);

workspaces/ballerina/ballerina-extension/src/features/ai/service/datamapper/datamapper.ts

Lines changed: 130 additions & 38 deletions
Large diffs are not rendered by default.

workspaces/ballerina/ballerina-extension/src/features/ai/service/datamapper/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ export interface RepairedFiles {
5353
repairedFiles: SourceFile[];
5454
}
5555

56+
export interface CodeRepairResult {
57+
finalContent: string;
58+
customFunctionsContent: string;
59+
}
60+
5661
// =============================================================================
5762
// MAPPING HINTS
5863
// =============================================================================

workspaces/ballerina/ballerina-extension/src/rpc-managers/ai-panel/repair-utils.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,94 @@ export async function addMissingRequiredFields(
330330

331331
return projectModified;
332332
}
333+
334+
export async function addCheckExpressionErrors(
335+
diagnosticsResult: Diagnostics[],
336+
langClient: ExtendedLangClient
337+
): Promise<boolean> {
338+
let projectModified = false;
339+
340+
for (const diag of diagnosticsResult) {
341+
const fileUri = diag.uri;
342+
const diagnostics = diag.diagnostics;
343+
344+
// Filter BCE3032 diagnostics (check expression errors)
345+
const bce3032Diagnostics = diagnostics.filter(d => d.code === "BCE3032");
346+
if (!bce3032Diagnostics.length) {
347+
continue;
348+
}
349+
350+
const astModifications: STModification[] = [];
351+
352+
// Process each diagnostic individually
353+
for (const diagnostic of bce3032Diagnostics) {
354+
try {
355+
// Get code actions for the diagnostic
356+
const codeActions = await langClient.codeAction({
357+
textDocument: { uri: fileUri },
358+
range: {
359+
start: diagnostic.range.start,
360+
end: diagnostic.range.end
361+
},
362+
context: {
363+
diagnostics: [diagnostic],
364+
only: ['quickfix'],
365+
triggerKind: 1
366+
}
367+
});
368+
369+
if (!codeActions?.length) {
370+
console.warn(`No code actions returned for ${fileUri} at line ${diagnostic.range.start.line}`);
371+
continue;
372+
}
373+
374+
// Find the action that adds error to return type
375+
// The language server typically provides actions like "Change return type to ..."
376+
const action = codeActions.find(
377+
action => action.title && action.title.includes("return")
378+
);
379+
380+
if (!action?.edit?.documentChanges?.length) {
381+
continue;
382+
}
383+
384+
const docEdit = action.edit.documentChanges[0] as TextDocumentEdit;
385+
386+
// Process all edits from the code action
387+
for (const edit of docEdit.edits) {
388+
astModifications.push({
389+
startLine: edit.range.start.line,
390+
startColumn: edit.range.start.character,
391+
endLine: edit.range.end.line,
392+
endColumn: edit.range.end.character,
393+
type: "INSERT",
394+
isImport: false,
395+
config: { STATEMENT: edit.newText }
396+
});
397+
}
398+
} catch (err) {
399+
console.warn(`Could not apply code action for ${fileUri} at line ${diagnostic.range.start.line}:`, err);
400+
}
401+
}
402+
403+
// Apply modifications to syntax tree
404+
if (astModifications.length > 0) {
405+
const syntaxTree = await langClient.stModify({
406+
documentIdentifier: { uri: fileUri },
407+
astModifications: astModifications
408+
});
409+
410+
// Update file content
411+
const { source } = syntaxTree as SyntaxTree;
412+
if (!source) {
413+
// Handle the case where source is undefined, when compiler issue occurs
414+
return false;
415+
}
416+
const absolutePath = fileURLToPath(fileUri);
417+
writeBallerinaFileDidOpenTemp(absolutePath, source);
418+
projectModified = true;
419+
}
420+
}
421+
422+
return projectModified;
423+
}

workspaces/ballerina/ballerina-extension/src/rpc-managers/ai-panel/rpc-manager.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,23 @@ export class AiPanelRpcManager implements AIPanelAPI {
662662
throw new Error("Not a Ballerina project.");
663663
}
664664
await addToIntegration(projectPath, params.fileChanges);
665-
updateView();
665+
666+
const context = StateMachine.context();
667+
const dataMapperMetadata = context.dataMapperMetadata;
668+
if (!dataMapperMetadata || !dataMapperMetadata.codeData) {
669+
updateView();
670+
return true;
671+
}
672+
673+
// Refresh data mapper with the updated code
674+
let filePath = dataMapperMetadata.codeData.lineRange?.fileName;
675+
const varName = dataMapperMetadata.name;
676+
if (!filePath || !varName) {
677+
updateView();
678+
return true;
679+
}
680+
681+
await refreshDataMapper(filePath, dataMapperMetadata.codeData, varName);
666682
return true;
667683
} catch (error) {
668684
console.error(">>> Failed to add files to the project", error);

workspaces/ballerina/ballerina-extension/src/rpc-managers/ai-panel/utils.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { getAskResponse } from "../../../src/features/ai/service/ask/ask";
2828
import { MappingFileRecord} from "./types";
2929
import { generateAutoMappings, generateRepairCode } from "../../../src/features/ai/service/datamapper/datamapper";
3030
import { ArtifactNotificationHandler, ArtifactsUpdated } from "../../utils/project-artifacts-handler";
31+
import { CopilotEventHandler } from "../../../src/features/ai/service/event";
3132

3233
// const BACKEND_BASE_URL = BACKEND_URL.replace(/\/v2\.0$/, "");
3334
//TODO: Temp workaround as custom domain seem to block file uploads
@@ -154,15 +155,18 @@ async function convertAttachmentToFileData(attachment: Attachment): Promise<File
154155
// Processes data mapper model and optional mapping instruction files to generate mapping expressions
155156
export async function generateMappingExpressionsFromModel(
156157
dataMapperModel: DMModel,
157-
mappingInstructionFiles: Attachment[] = []
158+
mappingInstructionFiles: Attachment[] = [],
159+
eventHandler: CopilotEventHandler
158160
): Promise<Mapping[]> {
159161
let dataMapperResponse: DataMapperModelResponse = {
160162
mappingsModel: dataMapperModel as DMModel
161163
};
162164
if (mappingInstructionFiles.length > 0) {
165+
eventHandler({ type: "content_block", content: "\n<progress>Processing mapping hints from attachments...</progress>" });
163166
const enhancedResponse = await enrichModelWithMappingInstructions(mappingInstructionFiles, dataMapperResponse);
164167
dataMapperResponse = enhancedResponse as DataMapperModelResponse;
165168
}
169+
eventHandler({ type: "content_block", content: "\n<progress>Generating data mappings...</progress>" });
166170

167171
const generatedMappings = await generateAutoMappings(dataMapperResponse);
168172
return generatedMappings.map(mapping => ({

0 commit comments

Comments
 (0)