import * as vscode from 'vscode' ; import * as xml from 'xmlbuilder2' ; import { XMLSerializedAsObject , XMLSerializedAsObjectArray } from 'xmlbuilder2/lib/interfaces' ; import { MavenTreeNode } from '../treeDataProviders/dependenciesTree/dependenciesRoot/mavenTree' ; import { DependenciesTreeNode } from '../treeDataProviders/dependenciesTree/dependenciesTreeNode' ; import { TreesManager } from '../treeDataProviders/treesManager' ; import { MavenUtils } from '../utils/mavenUtils' ; import { AbstractExclusion } from './abstractExclusion' ; export class MavenExclusion extends AbstractExclusion { private static readonly DEPENDENCY_INDENTATIONS : number = 2 ; constructor ( private _treesManager ) { super ( MavenUtils . PKG_TYPE ) ; } @override  public async excludeDependency ( dependenciesTreeNode ) { if ( dependenciesTreeNode . isDependenciesTreeRoot ( ) || dependenciesTreeNode . parent instanceof MavenTreeNode ) { return ; } let directDependency = this . getRootDependency ( dependenciesTreeNode ) ; if ( ! directDependency ) { return ; } let textDocument = await MavenUtils . openPomXml ( directDependency ) ; if ( ! textDocument ) { return ; } let pomXmlContent = textDocument . getText ( ) ; let [ groupId , artifactId ] = MavenUtils . getGavArray ( directDependency ) ; let dependencyStr = MavenUtils . getDependencyTag ( pomXmlContent , groupId , artifactId ) ; if ( dependencyStr === '' ) { return ; } let dependencyObj = xml . fragment ( dependencyStr ) . end ( { format : 'object' } ) as XMLSerializedAsObject ; this . addExclusion ( dependenciesTreeNode , dependencyObj ) ; let dependencyOffset = pomXmlContent . indexOf ( dependencyStr ) ; let startPos = textDocument . positionAt ( dependencyOffset ) ; let endPos = textDocument . positionAt ( dependencyOffset + dependencyStr . length ) ; await this . saveExclusion ( textDocument , startPos , endPos , dependencyObj ) ; this . _treesManager . treeDataProviderManager . removeNode ( dependenciesTreeNode ) ; this . highlightExclusionsTag ( textDocument , startPos ) ; } param dependenciesTreeNode private getRootDependency ( dependenciesTreeNode ) { while ( dependenciesTreeNode . parent && ! ( dependenciesTreeNode instanceof MavenTreeNode || dependenciesTreeNode . parent instanceof MavenTreeNode ) ) { dependenciesTreeNode = dependenciesTreeNode . parent as DependenciesTreeNode ; } return dependenciesTreeNode ; } param groupId param artifactId private createExclusion ( groupId , artifactId ) { let exclusionStr = '<exclusion><groupId>' + groupId + '</groupId><artifactId>' + artifactId + '</artifactId></exclusion>' ; return xml . convert ( exclusionStr , { format : 'object' } ) as XMLSerializedAsObject ; } exclusionNode dependencyObj private addExclusion ( exclusionNode , dependencyObj ) { let dependencyXmlTag = dependencyObj [ 'dependency' ] as XMLSerializedAsObject ; let [ groupId , artifactId ] = MavenUtils . getGavArray ( exclusionNode ) ; let exclusion = this . createExclusion ( groupId , artifactId ) ; let exclusionsXmlTag = dependencyXmlTag [ 'exclusions' ] as XMLSerializedAsObject ; if ( ! exclusionsXmlTag ) { dependencyXmlTag [ 'exclusions' ] = exclusion ; return ; } let exclusionsArr = exclusionsXmlTag [ '#' ] as XMLSerializedAsObjectArray ; if ( ! exclusionsArr ) { exclusionsArr = [ exclusionsXmlTag ] ; } exclusionsArr . map ( exclusionTagParent => exclusionTagParent as XMLSerializedAsObject ) . filter ( exclusionTagParent => exclusionTagParent . exclusion ) . forEach ( ( exclusionTagParent ) => { if ( exclusionTagParent . exclusion instanceof Array ) { if ( this . isExclusionExistsInArray ( exclusionTagParent . exclusion , groupId , artifactId ) ) { return ; } exclusionTagParent . exclusion . push ( exclusion . exclusion as XMLSerializedAsObject ) ; } else { if ( this . isExclusionExists ( exclusionTagParent . exclusion as XMLSerializedAsObject , groupId , artifactId ) ) { return ; } exclusionTagParent . exclusion = [ exclusionTagParent . exclusion , exclusion . exclusion as XMLSerializedAsObject ] ; } } ) ; dependencyXmlTag [ 'exclusions' ] = exclusionsXmlTag ; } param textDocument param startPos param endPos param dependencyObj private async saveExclusion ( textDocument , startPos , endPos , dependencyObj ) { let dependencyWithExclusionStr = xml . fragment ( dependencyObj ) . end ( { prettyPrint : true , indent : ' ' . repeat ( startPos . character / MavenExclusion . DEPENDENCY_INDENTATIONS ) , offset : MavenExclusion . DEPENDENCY_INDENTATIONS } ) . replace ( /^(\s*)/ , '' ) ; let textEdit = await vscode . window . showTextDocument ( textDocument ) ; await textEdit . edit ( textEdit => { textEdit . replace ( new vscode . Range ( startPos , endPos ) , dependencyWithExclusionStr ) ; } ) ; await textDocument . save ( ) ; } param exclusions param groupId param artifactId private isExclusionExistsInArray ( exclusions , groupId , artifactId ) { return ! ! exclusions . find ( exclusion => this . isExclusionExists ( exclusion as XMLSerializedAsObject , groupId , artifactId ) ) ; } param exclusions param groupId param artifactId private isExclusionExists ( exclusion , groupId , artifactId ) { return exclusion . artifactId === artifactId && exclusion . groupId === groupId ; } param textDocument param dependencyPos private highlightExclusionsTag ( textDocument , dependencyPos ) { let offset = textDocument . offsetAt ( dependencyPos ) ; let text = textDocument . getText ( ) ; vscode . window . showTextDocument ( textDocument , { selection : new vscode . Selection ( textDocument . positionAt ( text . indexOf ( '<exclusions>' , offset ) ) , textDocument . positionAt ( text . indexOf ( '</exclusions>' , offset ) + 13 ) ) } as vscode . TextDocumentShowOptions ) ; } }