import { map , flatMap } from "lodash" ; import { Range } from "vscode-languageserver-textdocument" ; import { Diagnostic , Range as LSPRange , TextDocument , CodeAction , Command , CodeActionKind , TextDocumentEdit , TextEdit , } from "vscode-languageserver-types" ; import { parse , DocumentCstNode } from "@xml-tools/parser" ; import { buildAst , XMLDocument } from "@xml-tools/ast" ; import { validateXMLView , validators , } from "@ui5-language-assistant/xml-views-validation" ; import { UI5SemanticModel } from "@ui5-language-assistant/semantic-model-types" ; import { computeQuickFixStableIdInfo } from "@ui5-language-assistant/xml-views-quick-fix" ; import { validations , commands , } from "@ui5-language-assistant/user-facing-text" ; import { LSPRangeToOffsetRange , offsetRangeToLSPRange } from "./range-utils" ; type QuickFixStableIdLSPInfo = { newText : string ; replaceRange : Range ; } ; export function diagnosticToCodeActionFix ( document , diagnostics , ui5Model ) { const documentText = document . getText ( ) ; const { cst , tokenVector } = parse ( documentText ) ; const xmlDocAst = buildAst ( cst as DocumentCstNode , tokenVector ) ; const codeActions = flatMap ( diagnostics , ( diagnostic ) => { switch ( diagnostic . code ) { case validations . NON_STABLE_ID . code : { return computeCodeActionsForQuickFixStableId ( { document , xmlDocument : xmlDocAst , nonStableIdDiagnostic : diagnostic , ui5Model , } ) ; } default : return [ ] ; } } ) ; return codeActions ; } function computeCodeActionsForQuickFixStableId ( opts ) { let codeActions = [ ] ; const errorOffset = LSPRangeToOffsetRange ( opts . nonStableIdDiagnostic . range , opts . document ) ; const quickFixStableIdInfo = computeQuickFixStableIdInfo ( opts . xmlDocument , [ errorOffset , ] ) ; const replaceRange = offsetRangeToLSPRange ( quickFixStableIdInfo [ 0 ] . replaceRange , opts . document ) ; codeActions . push ( CodeAction . create ( commands . QUICK_FIX_STABLE_ID_ERROR . title , Command . create ( commands . QUICK_FIX_STABLE_ID_ERROR . title , commands . QUICK_FIX_STABLE_ID_ERROR . name , opts . document . uri , opts . document . version , replaceRange , quickFixStableIdInfo [ 0 ] . newText ) , CodeActionKind . QuickFix ) ) ; const quickFixFileStableIdCodeActions = computeCodeActionsForQuickFixFileStableId ( { document : opts . document , xmlDocument : opts . xmlDocument , ui5Model : opts . ui5Model , } ) ; codeActions = codeActions . concat ( quickFixFileStableIdCodeActions ) ; return codeActions ; } function computeCodeActionsForQuickFixFileStableId ( opts ) { const actualValidators = { document : [ ] , element : [ validators . validateNonStableId ] , attribute : [ ] , } ; const nonStableIdFileIssues = validateXMLView ( { validators : actualValidators , model : opts . ui5Model , xmlView : opts . xmlDocument , } ) ; if ( nonStableIdFileIssues . length === 1 ) { return [ ] ; } const errorsOffset = map ( nonStableIdFileIssues , ( _ ) => _ . offsetRange ) ; const nonStableIdFileIssuesInfo = computeQuickFixStableIdInfo ( opts . xmlDocument , errorsOffset ) ; const nonStableIdFileIssuesLSPInfo = map ( nonStableIdFileIssuesInfo , ( _ ) => ( { newText : _ . newText , replaceRange : offsetRangeToLSPRange ( _ . replaceRange , opts . document ) , } ) ) ; return [ CodeAction . create ( commands . QUICK_FIX_STABLE_ID_FILE_ERRORS . title , Command . create ( commands . QUICK_FIX_STABLE_ID_FILE_ERRORS . title , commands . QUICK_FIX_STABLE_ID_FILE_ERRORS . name , opts . document , opts . document . uri , opts . document . version , nonStableIdFileIssuesLSPInfo ) , CodeActionKind . QuickFix ) , ] ; } export function executeQuickFixStableIdCommand ( opts ) { const documentEdit = [ TextDocumentEdit . create ( { uri : opts . documentUri , version : opts . documentVersion } , [ TextEdit . replace ( opts . quickFixReplaceRange , `${ opts . quickFixNewText }` ) ] ) , ] ; return documentEdit ; } export function executeQuickFixFileStableIdCommand ( opts ) { const textEdits = map ( opts . nonStableIdIssues , ( _ ) => TextEdit . replace ( _ . replaceRange , `${ _ . newText }` ) ) ; const documentEdit = [ TextDocumentEdit . create ( { uri : opts . documentUri , version : opts . documentVersion } , textEdits ) , ] ; return documentEdit ; }