import * as fse from "fs-extra" ; import * as vscode from "vscode" ; import { Dependency } from "../explorer/model/Dependency" ; import { getIndentation } from "../utils/editUtils" ; import { UserError } from "../utils/errorUtils" ; import { ElementNode , getNodesByTag , XmlTagName } from "../utils/lexerUtils" ; export async function excludeDependencyHandler ( toExclude ? ) { if ( toExclude === undefined ) { throw new UserError ( "Only Dependency can be excluded." ) ; } const root = toExclude . root ; if ( root === undefined || toExclude . fullArtifactName === root . fullArtifactName ) { vscode . window . showInformationMessage ( "The dependency written in pom can not be excluded." ) ; return ; } const pomPath = toExclude . projectPomPath ; if ( ! await fse . pathExists ( pomPath ) ) { throw new UserError ( "Specified POM file does not exist on file system." ) ; } await excludeDependency ( pomPath , toExclude . groupId , toExclude . artifactId , root . groupId , root . artifactId ) ; } async function excludeDependency ( pomPath , gid , aid , rootGid , rootAid ) { const pomDocument = await vscode . window . showTextDocument ( vscode . Uri . file ( pomPath ) , { preserveFocus : true } ) ; const projectNodes = getNodesByTag ( pomDocument . document . getText ( ) , XmlTagName . Project ) ; if ( projectNodes === undefined || projectNodes . length !== 1 ) { throw new UserError ( "Only support POM file with single <project> node." ) ; } const projectNode = projectNodes [ 0 ] ; const dependenciesNode = projectNode . children ?. find ( node => node . tag === XmlTagName . Dependencies ) ; const dependencyNode = dependenciesNode ?. children ?. find ( node => node . children ?. find ( id => id . tag === XmlTagName . GroupId && id . text === rootGid ) && node . children ?. find ( id => id . tag === XmlTagName . ArtifactId && id . text === rootAid ) ) ; if ( dependencyNode === undefined ) { throw new Error ( `Failed to find the dependency where ${ gid }:${ aid } is introduced.` ) ; } else { await insertExcludeDependency ( pomPath , dependencyNode , gid , aid ) ; } } async function insertExcludeDependency ( pomPath , targetNode , gid , aid ) { if ( targetNode . children === undefined || targetNode . contentStart === undefined || targetNode . contentEnd === undefined ) { throw new UserError ( "Invalid target XML node to delete dependency." ) ; } const currentDocument = await vscode . workspace . openTextDocument ( pomPath ) ; const textEditor = await vscode . window . showTextDocument ( currentDocument ) ; const baseIndent = getIndentation ( currentDocument , targetNode . contentEnd ) ; const options = textEditor . options ; const indent = options . insertSpaces && typeof options . tabSize === "number" ? " " . repeat ( options . tabSize ) : "\t" ; const eol = currentDocument . eol === vscode . EndOfLine . LF ? "\n" : "\r\n" ; let insertPosition ; let targetText ; const exclusionNode = targetNode . children ?. find ( node => node . tag === XmlTagName . Exclusions ) ; if ( exclusionNode === undefined ) { insertPosition = currentDocument . positionAt ( targetNode . contentEnd ) ; targetText = constructExclusionsNode ( gid , aid , baseIndent , indent , eol ) ; } else { if ( exclusionNode . contentStart === undefined ) { throw new UserError ( "Invalid insert position." ) ; } insertPosition = currentDocument . positionAt ( exclusionNode . contentStart ) ; targetText = constructExclusionNode ( gid , aid , baseIndent , indent , eol ) ; } const edit = new vscode . WorkspaceEdit ( ) ; edit . insert ( currentDocument . uri , insertPosition , targetText ) ; await vscode . workspace . applyEdit ( edit ) ; const endingPosition = currentDocument . positionAt ( currentDocument . offsetAt ( insertPosition ) + targetText . length ) ; textEditor . revealRange ( new vscode . Range ( insertPosition , endingPosition ) ) ; } function constructExclusionsNode ( gid , aid , baseIndent , indent , eol ) { return [ `${ indent }<exclusions>` , `${ indent }<exclusion>` , `${ indent }${ indent }<artifactId>${ aid }</artifactId>` , `${ indent }${ indent }<groupId>${ gid }</groupId>` , `${ indent }</exclusion>` , `</exclusions>${ eol }${ baseIndent }` ] . join ( `${ eol }${ baseIndent }${ indent }` ) ; } function constructExclusionNode ( gid , aid , baseIndent , indent , eol ) { return [ `${ eol }${ baseIndent }${ indent }${ indent }<exclusion>` , `${ indent }${ indent }<artifactId>${ aid }</artifactId>` , `${ indent }${ indent }<groupId>${ gid }</groupId>` , `${ indent }</exclusion>` ] . join ( `${ eol }${ baseIndent }${ indent }` ) ; }