import { XMLParser } from "ui5plugin-parser" ; import { SAPNodeDAO } from "ui5plugin-parser/dist/classes/librarydata/SAPNodeDAO" ; import { StandardUIClass } from "ui5plugin-parser/dist/classes/UI5Classes/UI5Parser/UIClass/StandardUIClass" ; import { TextDocumentTransformer } from "ui5plugin-parser/dist/classes/utils/TextDocumentTransformer" ; import { URLBuilder } from "ui5plugin-parser/dist/classes/utils/URLBuilder" ; import * as vscode from "vscode" ; import { UI5Plugin } from "../../../../UI5Plugin" ; import { TextDocumentAdapter } from "../../../adapters/vscode/TextDocumentAdapter" ; export class XMLHoverProvider { static getTextEdits ( document , position ) { const range = document . getWordRangeAtPosition ( position ) ; const word = document . getText ( range ) ; const offset = document . offsetAt ( position ) ; let hover ; const XMLFile = TextDocumentTransformer . toXMLFile ( new TextDocumentAdapter ( document ) ) ; if ( XMLFile ) { const allTags = XMLParser . getAllTags ( XMLFile ) ; const tag = allTags . find ( tag => tag . positionBegin < offset && tag . positionEnd >= offset ) ; if ( tag ) { const tagName = XMLParser . getClassNameFromTag ( tag . text ) ; const classOfTheTag = XMLParser . getClassNameInPosition ( XMLFile , offset ) ; const attributes = XMLParser . getAttributesOfTheTag ( tag ) ; const attribute = attributes ?. find ( attribute => { const { attributeName } = XMLParser . getAttributeNameAndValue ( attribute ) ; return attributeName === word ; } ) ; if ( attribute ) { const { attributeName } = XMLParser . getAttributeNameAndValue ( attribute ) ; const text = this . _getTextIfItIsFieldOrMethodOfClass ( classOfTheTag , attributeName ) ; if ( text ) { const markdownString = new vscode . MarkdownString ( ) ; markdownString . appendCodeblock ( `class ${ classOfTheTag }  \n` ) ; markdownString . appendMarkdown ( text ) ; hover = new vscode . Hover ( markdownString ) ; } } else if ( tagName === word ) { const isClassName = word [ 0 ] . toUpperCase ( ) === word [ 0 ] ; if ( isClassName ) { const markdownString = new vscode . MarkdownString ( ) ; markdownString . appendCodeblock ( `class ${ classOfTheTag }  \n` ) ; const UIClass = UI5Plugin . getInstance ( ) . parser . classFactory . getUIClass ( classOfTheTag ) ; const node = new SAPNodeDAO ( ) . findNode ( UIClass . className ) ; let classDescription = node ?. getMetadata ( ) ?. getRawMetadata ( ) ?. description || "" ; classDescription = StandardUIClass . removeTags ( classDescription ) ; const description = classDescription ? `  \n${ classDescription }` : "" ; const text = `${ URLBuilder . getInstance ( ) . getMarkupUrlForClassApi ( UIClass ) }${ description }` ; markdownString . appendMarkdown ( text ) ; hover = new vscode . Hover ( markdownString ) ; } else { let parentTag = XMLParser . getParentTagAtPosition ( XMLFile , offset ) ; const tagClass = XMLParser . getClassNameInPosition ( XMLFile , parentTag . positionBegin ) ; if ( ! this . _isThisAClass ( tagClass ) ) { parentTag = XMLParser . getParentTagAtPosition ( XMLFile , parentTag . positionBegin - 1 ) ; } const classOfTheTag = XMLParser . getClassNameInPosition ( XMLFile , parentTag . positionBegin ) ; const text = this . _getTextIfItIsFieldOrMethodOfClass ( classOfTheTag , word ) ; if ( text ) { const markdownString = new vscode . MarkdownString ( ) ; markdownString . appendCodeblock ( `class ${ classOfTheTag }  \n` ) ; markdownString . appendMarkdown ( text ) ; hover = new vscode . Hover ( markdownString ) ; } } } } } return hover ; } private static _isThisAClass ( name ) { const classNameParts = name . split ( "." ) ; const lastPart = classNameParts [ classNameParts . length - 1 ] ; const isClass = lastPart [ 0 ] === lastPart [ 0 ] . toUpperCase ( ) ; return isClass ; } private static _getTextIfItIsFieldOrMethodOfClass ( className , attributeName ) { let text = "" ; const UIClass = UI5Plugin . getInstance ( ) . parser . classFactory . getUIClass ( className ) ; const aggregation = UIClass . aggregations . find ( aggregation => aggregation . name === attributeName ) ; const event = UIClass . events . find ( event => event . name === attributeName ) ; const property = UIClass . properties . find ( property => property . name === attributeName ) ; let api = "" ; if ( aggregation ) { text = `aggregation: **${ aggregation . name }**  \ntype: **${ aggregation . type }**  \nmultiple: ${ aggregation . multiple }  \n\n${ aggregation . description }` ; api = URLBuilder . getInstance ( ) . getMarkupUrlForAggregationApi ( UIClass ) ; } if ( event ) { text = `event: **${ event . name }**  \n\n${ event . description }` ; api = URLBuilder . getInstance ( ) . getMarkupUrlForEventsApi ( UIClass , event . name ) ; if ( event . params . length > 0 ) { text += `  \n\nParameters:  \n${ event . params . map ( param => `*${ param . name }*: ${ param . type }` ) . join ( "  \n" ) }` ; } } if ( property ) { text = `property: **${ property . name }**  \ntype: **${ property . type }**  \n\n${ property . description }` ; const typeValues = property . typeValues . map ( typeValue => `*${ typeValue . text }* - ${ typeValue . description }` ) ; if ( typeValues . length > 0 ) { text += `  \n\nValues:  \n${ typeValues . join ( "  \n" ) }` ; } api = URLBuilder . getInstance ( ) . getMarkupUrlForPropertiesApi ( UIClass ) ; } if ( api ) { text = `${ api }  \n${ text }` ; } if ( ! text && UIClass . parentClassNameDotNotation ) { text = this . _getTextIfItIsFieldOrMethodOfClass ( UIClass . parentClassNameDotNotation , attributeName ) ; } return text ; } }