import { Location } from "vscode" ; import { configKeys } from "../../../common" ; import { ext } from "../../extensionVariables" ; import { assert } from "../../fixed_assert" ; import { Span } from "../../language/Span" ; import { IGotoResourcesArgs } from "../../vscodeIntegration/commandArguments" ; import { getVSCodeRangeFromSpan } from "../../vscodeIntegration/vscodePosition" ; import { ResolvableCodeLens } from "../DeploymentDocument" ; import { IJsonResourceInfo } from "./getResourcesInfo" ; import { TemplateScope } from "./scopes/TemplateScope" ; export function getParentAndChildCodeLenses ( scope , infos ) { if ( ! ext . configuration . get < boolean > ( configKeys . codeLensForResourceParentsAndChildren ) ) { return [ ] ; } const lenses = [ ] ; for ( const resource of infos ) { if ( ! ! resource . parent ) { lenses . push ( new ParentCodeLens ( scope , resource ) ) ; } if ( resource . children . length > 0 ) { lenses . push ( new ChildrenCodeLens ( scope , resource ) ) ; } } return lenses ; } export abstract class ParentOrChildCodeLens extends ResolvableCodeLens { public constructor ( scope , protected readonly sourceResource ) { super ( scope , ParentOrChildCodeLens . getCodeLensSpan ( scope , sourceResource ) ) ; } private static getCodeLensSpan ( scope , sourceResource ) { const resourceSpan = sourceResource . resourceObject . span ; const resourceFirstLine = scope . document . getDocumentPosition ( resourceSpan . startIndex ) . line ; let lensStartIndex = scope . document . getDocumentCharacterIndex ( resourceFirstLine + 1 , 0 ) ; const lensEndIndex = resourceSpan . endIndex ; if ( lensStartIndex > lensEndIndex ) { lensStartIndex = resourceSpan . startIndex ; assert ( lensStartIndex <= lensEndIndex ) ; } return new Span ( lensStartIndex , lensEndIndex - lensStartIndex ) ; } protected resolveCore ( title , targets , kind ) { if ( targets . length > 0 ) { const targetLocations = targets . map ( resInfo => new Location ( this . scope . document . documentUri , getVSCodeRangeFromSpan ( this . scope . document , resInfo . resourceObject . span ) ) ) ; this . command = { title : title , command : 'azurerm-vscode-tools.codeLens.gotoResources' , arguments : [ < IGotoResourcesArgs > { source : { uri : this . scope . document . documentUri , range : this . range } , targets : targetLocations , telemetryProperties : { kind , targetCount : String ( targets . length ) } } ] } ; } else { this . command = { title : title , command : '' } ; } return true ; } } /**
 * A code lens that displays the children of a resource
 */ export class ChildrenCodeLens extends ParentOrChildCodeLens { public constructor ( scope , sourceResource ) { super ( scope , sourceResource ) ; } public async resolve ( ) { let title ; const children = < IJsonResourceInfo [ ] > this . sourceResource ?. children ?? [ ] ; if ( children . length > 0 ) { const countOfChildrenTitle = `${ children . length } ${ children . length === 1 ? "child" : "children" }` ; const childrenLabels = children . map ( child => ( < IJsonResourceInfo > child ) . getFriendlyResourceLabel ( { } ) ) . join ( ", " ) ; title = `${ countOfChildrenTitle }: ${ childrenLabels }` ; } else { title = "No children" ; } return super . resolveCore ( title , children , 'children' ) ; } } /**
 * A code lens that displays the parent of a resource
 */ export class ParentCodeLens extends ParentOrChildCodeLens { public constructor ( scope , sourceResource ) { super ( scope , sourceResource ) ; } public async resolve ( ) { const parent = < IJsonResourceInfo | undefined > this . sourceResource ?. parent ; let title ; if ( parent ) { title = `Parent: ${ parent . getFriendlyResourceLabel ( { } ) }` ; } else { title = "No parent" ; } return super . resolveCore ( title , parent ? [ parent ] : [ ] , 'parent' ) ; } }