@@ -721,93 +721,97 @@ class WARoot {
721721 addPartiallyAudited ( relativePath : string ) : void {
722722 // check if file is already in list
723723 const index = this . auditedFiles . findIndex ( ( file ) => file . path === relativePath ) ;
724-
725724 // if file is already audited ignore
726725 if ( index > - 1 ) {
727726 return ;
728727 }
729728
730- const location = this . getActiveSelectionLocation ( ) ;
731- const alreadyMarked = this . partiallyAuditedFiles . findIndex (
732- ( file ) => file . path === relativePath && file . startLine <= location . startLine && file . endLine >= location . endLine ,
733- ) ;
729+ const locations = this . getActiveSelectionLocation ( ) ;
734730
735- // this section is already marked. Remove it then
736- if ( alreadyMarked > - 1 ) {
737- // Splits the existing entry into 2 and remove the location marked by the user
738- const previousMarkedEntry = this . partiallyAuditedFiles [ alreadyMarked ] ;
731+ // Process each selection/location separately
732+ for ( const location of locations ) {
733+ const alreadyMarked = this . partiallyAuditedFiles . findIndex (
734+ ( file ) => file . path === relativePath && file . startLine <= location . startLine && file . endLine >= location . endLine ,
735+ ) ;
739736
740- // same area has been selected so lets delete it
741- if ( previousMarkedEntry . startLine === location . startLine && previousMarkedEntry . endLine === location . endLine ) {
742- this . partiallyAuditedFiles . splice ( alreadyMarked , 1 ) ;
743- } else {
744- // not the same area so we need to split the entry or change it
737+ // this section is already marked. Remove it then
738+ if ( alreadyMarked > - 1 ) {
739+ // Splits the existing entry into 2 and remove the location marked by the user
740+ const previousMarkedEntry = this . partiallyAuditedFiles [ alreadyMarked ] ;
745741
746- const locationClone = { ...previousMarkedEntry } ;
742+ // same area has been selected so lets delete it
743+ if ( previousMarkedEntry . startLine === location . startLine && previousMarkedEntry . endLine === location . endLine ) {
744+ this . partiallyAuditedFiles . splice ( alreadyMarked , 1 ) ;
745+ } else {
746+ // not the same area so we need to split the entry or change it
747747
748- // if either the end line or the start line is the same we don't need
749- // to split the entry but can just adjust the current one
750- let splitNeeded = true ;
751- if ( previousMarkedEntry . endLine === location . endLine ) {
752- previousMarkedEntry . endLine = location . startLine - 1 ;
753- splitNeeded = false ;
754- }
748+ const locationClone = { ...previousMarkedEntry } ;
755749
756- if ( previousMarkedEntry . startLine === location . startLine ) {
757- previousMarkedEntry . startLine = location . endLine + 1 ;
758- splitNeeded = false ;
759- }
750+ // if either the end line or the start line is the same we don't need
751+ // to split the entry but can just adjust the current one
752+ let splitNeeded = true ;
753+ if ( previousMarkedEntry . endLine === location . endLine ) {
754+ previousMarkedEntry . endLine = location . startLine - 1 ;
755+ splitNeeded = false ;
756+ }
760757
761- if ( splitNeeded ) {
762- previousMarkedEntry . endLine = location . startLine - 1 ;
763- locationClone . startLine = location . endLine + 1 ;
758+ if ( previousMarkedEntry . startLine === location . startLine ) {
759+ previousMarkedEntry . startLine = location . endLine + 1 ;
760+ splitNeeded = false ;
761+ }
764762
765- this . partiallyAuditedFiles . push ( locationClone ) ;
766- }
763+ if ( splitNeeded ) {
764+ previousMarkedEntry . endLine = location . startLine - 1 ;
765+ locationClone . startLine = location . endLine + 1 ;
766+
767+ this . partiallyAuditedFiles . push ( locationClone ) ;
768+ }
767769
768- this . partiallyAuditedFiles [ alreadyMarked ] = previousMarkedEntry ;
770+ this . partiallyAuditedFiles [ alreadyMarked ] = previousMarkedEntry ;
771+ }
772+ } else {
773+ this . partiallyAuditedFiles . push ( {
774+ path : relativePath ,
775+ author : this . username ,
776+ startLine : location . startLine ,
777+ endLine : location . endLine ,
778+ } ) ;
769779 }
770- } else {
771- this . partiallyAuditedFiles . push ( {
772- path : relativePath ,
773- author : this . username ,
774- startLine : location . startLine ,
775- endLine : location . endLine ,
776- } ) ;
777780 }
778781
779782 this . mergePartialAudits ( ) ;
780783 }
781784
782785 /**
783- * Gets the active selection location .
784- * @returns A Location corresponding to the active selection location .
786+ * Gets the active selection locations, supporting multiple selections .
787+ * @returns An array of FullLocations corresponding to all active selections .
785788 */
786- getActiveSelectionLocation ( ) : FullLocation {
789+ getActiveSelectionLocation ( ) : FullLocation [ ] {
787790 // the null assertion is never undefined because we check if the editor is undefined
788791 const editor = vscode . window . activeTextEditor ! ;
789792 const uri = editor . document . uri ;
793+ const relativePath = path . relative ( this . rootPath , uri . fsPath ) ;
790794
791- const selectedCode = editor . selection ;
792- const startLine = selectedCode . start . line ;
795+ return editor . selections . map ( ( selection ) => {
796+ const startLine = selection . start . line ;
797+ let endLine = selection . end . line ;
793798
794- let endLine = selectedCode . end . line ;
795- // vscode sets the end of a fully selected line as the first character of the next line
796- // so we decrement the end line if the end character is 0 and the end line is not the same as the start line
797- if ( endLine > selectedCode . start . line && selectedCode . end . character === 0 ) {
798- endLine -- ;
799- }
799+ // vscode sets the end of a fully selected line as the first character of the next line
800+ // so we decrement the end line if the end character is 0 and the end line is not the same as the start line
801+ if ( endLine > selection . start . line && selection . end . character === 0 ) {
802+ endLine -- ;
803+ }
800804
801- // github preview does not show the preview if the last document line is empty
802- // so we decrement it by one
803- if ( endLine === editor . document . lineCount - 1 && editor . document . lineAt ( endLine ) . text === "" ) {
804- // ensure that we don't go before the start line
805- endLine = Math . max ( endLine - 1 , startLine ) ;
806- }
805+ // github preview does not show the preview if the last document line is empty
806+ // so we decrement it by one
807+ if ( endLine === editor . document . lineCount - 1 && editor . document . lineAt ( endLine ) . text === "" ) {
808+ // ensure that we don't go before the start line
809+ endLine = Math . max ( endLine - 1 , startLine ) ;
810+ }
807811
808- const relativePath = path . relative ( this . rootPath , uri . fsPath ) ;
809- // TODO: error if not in this workspace root?
810- return { path : relativePath , startLine , endLine , label : "" , description : "" , rootPath : this . rootPath } ;
812+ // TODO: error if not in this workspace root?
813+ return { path : relativePath , startLine , endLine , label : "" , description : "" , rootPath : this . rootPath } ;
814+ } ) ;
811815 }
812816
813817 /**
@@ -1466,7 +1470,7 @@ class MultiRootManager {
14661470 * @param uri The uri of the current file.
14671471 * @returns A FullLocation corresponding to the selection or undefined if the current file is not in any workspace root.
14681472 */
1469- getActiveSelectionLocation ( uri : vscode . Uri ) : FullLocation | undefined {
1473+ getActiveSelectionLocation ( uri : vscode . Uri ) : FullLocation [ ] | undefined {
14701474 const [ wsRoot , _relativePath ] = this . getCorrespondingRootAndPath ( uri . fsPath ) ;
14711475 const result = wsRoot ?. getActiveSelectionLocation ( ) ;
14721476 if ( result === undefined ) {
@@ -2086,10 +2090,13 @@ export class CodeMarker implements vscode.TreeDataProvider<TreeEntry> {
20862090 }
20872091
20882092 async getSelectedClientCodeAndPermalink ( ) : Promise < FromLocationResponse | void > {
2089- const location = this . getActiveSelectionLocation ( ) ;
2090- if ( location === undefined ) {
2093+ const locations = this . getActiveSelectionLocation ( ) ;
2094+ if ( locations === undefined || locations . length === 0 ) {
20912095 return ;
20922096 }
2097+
2098+ // Use the first (primary) selection if more than one is present
2099+ const location = locations [ 0 ] ;
20932100 const editor = vscode . window . activeTextEditor ! ;
20942101
20952102 const remoteAndPermalink = await this . getRemoteAndPermalink ( Repository . Client , location ) ;
@@ -2592,10 +2599,12 @@ export class CodeMarker implements vscode.TreeDataProvider<TreeEntry> {
25922599 * @param repository If the repository is the Audit repository or the Client repository
25932600 */
25942601 async copySelectedCodePermalink ( repository : Repository ) : Promise < void > {
2595- const location = this . getActiveSelectionLocation ( ) ;
2596- if ( location === undefined ) {
2602+ const locations = this . getActiveSelectionLocation ( ) ;
2603+ if ( locations === undefined || locations . length === 0 ) {
25972604 return ;
25982605 }
2606+ // Use the first selection
2607+ const location = locations [ 0 ] ;
25992608
26002609 const remoteAndPermalink = await this . getRemoteAndPermalink ( repository , location ) ;
26012610 if ( remoteAndPermalink === undefined ) {
@@ -2999,12 +3008,17 @@ export class CodeMarker implements vscode.TreeDataProvider<TreeEntry> {
29993008 return ;
30003009 }
30013010 const uri = editor . document . uri ;
3002- const location = this . workspaces . getActiveSelectionLocation ( uri ) ;
3011+ const locations = this . workspaces . getActiveSelectionLocation ( uri ) ;
30033012
3004- if ( location === undefined ) {
3013+ if ( locations === undefined ) {
30053014 vscode . window . showErrorMessage ( "Trying to add entries to a file outside this workspace: " + uri . fsPath ) ;
30063015 return ;
30073016 }
3017+ if ( locations . length === 0 ) {
3018+ return ;
3019+ }
3020+
3021+ const location = locations [ 0 ] ;
30083022
30093023 const intersectedIdx = this . getIntersectingTreeEntryIndex ( location , entryType ) ;
30103024
@@ -3026,7 +3040,7 @@ export class CodeMarker implements vscode.TreeDataProvider<TreeEntry> {
30263040 label : title ,
30273041 entryType : entryType ,
30283042 author : this . username ,
3029- locations : [ location ] ,
3043+ locations : locations ,
30303044 details : createDefaultEntryDetails ( ) ,
30313045 } ;
30323046 this . treeEntries . push ( entry ) ;
@@ -3053,18 +3067,18 @@ export class CodeMarker implements vscode.TreeDataProvider<TreeEntry> {
30533067 this . refresh ( uri ) ;
30543068 }
30553069
3056- getActiveSelectionLocation ( ) : FullLocation | undefined {
3070+ getActiveSelectionLocation ( ) : FullLocation [ ] | undefined {
30573071 // the null assertion is never undefined because we check if the editor is undefined
30583072 const editor = vscode . window . activeTextEditor ! ;
30593073 const uri = editor . document . uri ;
3060- const location = this . workspaces . getActiveSelectionLocation ( uri ) ;
3074+ const locations = this . workspaces . getActiveSelectionLocation ( uri ) ;
30613075
3062- if ( location === undefined ) {
3076+ if ( locations === undefined ) {
30633077 vscode . window . showErrorMessage ( `weAudit: Error determining location of selected code. Filepath: ${ uri . fsPath } is not in any workspace root.` ) ;
30643078 return ;
30653079 }
30663080
3067- return location ;
3081+ return locations ;
30683082 }
30693083
30703084 /**
@@ -3150,15 +3164,15 @@ export class CodeMarker implements vscode.TreeDataProvider<TreeEntry> {
31503164 if ( editor === undefined ) {
31513165 return ;
31523166 }
3153- const location = this . getActiveSelectionLocation ( ) ;
3154- if ( location === undefined ) {
3167+ const locations = this . getActiveSelectionLocation ( ) ;
3168+ if ( locations === undefined || locations . length === 0 ) {
31553169 return ;
31563170 }
31573171
31583172 // create a quick pick to select the entry to add the region to
31593173 const items = this . treeEntries
31603174 . filter ( ( entry ) => {
3161- if ( entry . locations . length === 0 || entry . locations [ 0 ] . rootPath !== location . rootPath ) {
3175+ if ( entry . locations . length === 0 || entry . locations [ 0 ] . rootPath !== locations [ 0 ] . rootPath ) {
31623176 return false ;
31633177 }
31643178 return true ;
@@ -3186,7 +3200,10 @@ export class CodeMarker implements vscode.TreeDataProvider<TreeEntry> {
31863200 return ;
31873201 }
31883202 const entry = pickItem . entry ;
3189- entry . locations . push ( location ) ;
3203+ // Add each selection as a separate region
3204+ for ( const location of locations ) {
3205+ entry . locations . push ( location ) ;
3206+ }
31903207 this . updateSavedData ( entry . author ) ;
31913208 this . decorateWithUri ( editor . document . uri ) ;
31923209 this . refresh ( editor . document . uri ) ;
0 commit comments