@@ -7,12 +7,14 @@ import { SQL_FN_INT8BITSTRING } from './utils';
77
88export class OurFileCoverage extends vscode . FileCoverage {
99
10+ public readonly name : string ;
1011 public readonly codeUnit : string ;
1112 private coverageIndex : number ;
1213
13- constructor ( coverageIndex : number , codeUnit : string , uri : vscode . Uri , statementCoverage : vscode . TestCoverageCount , branchCoverage ?: vscode . TestCoverageCount , declarationCoverage ?: vscode . TestCoverageCount , includesTests ?: vscode . TestItem [ ] ) {
14+ constructor ( coverageIndex : number , name : string , codeUnit : string , uri : vscode . Uri , statementCoverage : vscode . TestCoverageCount , branchCoverage ?: vscode . TestCoverageCount , declarationCoverage ?: vscode . TestCoverageCount , includesTests ?: vscode . TestItem [ ] ) {
1415 super ( uri , statementCoverage , branchCoverage , declarationCoverage , includesTests ) ;
1516 this . coverageIndex = coverageIndex ;
17+ this . name = name ;
1618 this . codeUnit = codeUnit ;
1719 }
1820
@@ -33,9 +35,30 @@ export class OurFileCoverage extends vscode.FileCoverage {
3335 } ;
3436 const namespace : string = server . namespace . toUpperCase ( ) ;
3537
38+ // When ObjectScript extension spreads method arguments over multiple lines, we need to compute offsets
39+ const mapOffsets : Map < string , number > = new Map ( ) ;
40+ if ( vscode . workspace . getConfiguration ( 'objectscript' , this . uri ) . get ( 'multilineMethodArgs' , false ) ) {
41+ const response = await makeRESTRequest (
42+ "POST" ,
43+ serverSpec ,
44+ { apiVersion : 1 , namespace, path : "/action/query" } ,
45+ {
46+ query : "SELECT Name as Method, SUM( CASE WHEN $LENGTH(FormalSpec, ',') > 1 THEN $LENGTH(FormalSpec, ',') ELSE 0 END ) OVER ( ORDER BY SequenceNumber ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS Offset FROM %Dictionary.MethodDefinition WHERE parent = ?" ,
47+ parameters : [ this . name ] ,
48+ } ,
49+ ) ;
50+ if ( response ) {
51+ response ?. data ?. result ?. content ?. forEach ( element => {
52+ const methodName = element . Method ;
53+ const offset = Number ( element . Offset ) ;
54+ mapOffsets . set ( methodName , offset ) ;
55+ } ) ;
56+ }
57+ }
58+
3659 // Get map of lines to methods
37- const mapMethods : Map < number , string > = new Map ( ) ;
38- const lineToMethod : string [ ] = [ ] ;
60+ const mapMethodsInCoverage : Map < number , string > = new Map ( ) ;
61+ const mapMethodsInDocument : Map < number , string > = new Map ( ) ;
3962 let response = await makeRESTRequest (
4063 "POST" ,
4164 serverSpec ,
@@ -46,14 +69,10 @@ export class OurFileCoverage extends vscode.FileCoverage {
4669 } ,
4770 ) ;
4871 if ( response ) {
49- let previousMethod = "" ;
50- let previousLine = 0 ;
5172 response ?. data ?. result ?. content ?. forEach ( element => {
5273 const thisLine = Number ( element . Line ) ;
53- mapMethods . set ( Number ( element . Line ) , element . Method ) ;
54- lineToMethod . fill ( previousMethod , previousLine , thisLine - 1 ) ;
55- previousMethod = element . Method ;
56- previousLine = thisLine ;
74+ mapMethodsInCoverage . set ( thisLine , element . Method ) ;
75+ mapMethodsInDocument . set ( thisLine + ( mapOffsets . get ( element . Method ) || 0 ) , element . Method ) ;
5776 } ) ;
5877 }
5978
@@ -80,14 +99,24 @@ export class OurFileCoverage extends vscode.FileCoverage {
8099 // Process the Uint8Bitstring values for executable and covered lines
81100 const i8bsExecutableLines = element . i8bsExecutableLines ;
82101 const i8bsCoveredLines = element . i8bsCoveredLines ;
102+
103+ let offset = 0 ; // We will add this to line number in coverage results to get line number in document, adjusted for multiline method arguments
83104 for ( let lineChunk = 0 ; lineChunk < i8bsExecutableLines . length ; lineChunk ++ ) {
84105 const executableLines = i8bsExecutableLines . charCodeAt ( lineChunk ) ;
85106 const coveredLines = i8bsCoveredLines . charCodeAt ( lineChunk ) ;
86107 for ( let bitIndex = 0 ; bitIndex < 8 ; bitIndex ++ ) {
108+ const lineNumberOfCoverage = lineChunk * 8 + bitIndex + 1 ;
109+
110+ // On a method declaration line we should recompute the offset
111+ const method = mapMethodsInCoverage . get ( lineNumberOfCoverage ) ;
112+ if ( method ) {
113+ offset = ( mapOffsets . get ( method ) || offset ) ;
114+ }
115+
87116 if ( ( executableLines & ( 1 << bitIndex ) ) !== 0 ) {
88- const lineNumber = lineChunk * 8 + bitIndex + 1 ;
89117 const isCovered = ( coveredLines & ( 1 << bitIndex ) ) !== 0 ;
90- const range = new vscode . Range ( new vscode . Position ( lineNumber - 1 , 0 ) , new vscode . Position ( lineNumber - 1 , Number . MAX_VALUE ) ) ;
118+ const lineNumberOfDocument = lineNumberOfCoverage + offset ;
119+ const range = new vscode . Range ( new vscode . Position ( lineNumberOfDocument - 1 , 0 ) , new vscode . Position ( lineNumberOfDocument - 1 , Number . MAX_VALUE ) ) ;
91120 const statementCoverage = new vscode . StatementCoverage ( isCovered , range ) ;
92121 detailedCoverage . push ( statementCoverage ) ;
93122 }
@@ -109,18 +138,26 @@ export class OurFileCoverage extends vscode.FileCoverage {
109138 if ( response ) {
110139 let previousMethod = "" ;
111140 let previousStartLine = 0 ;
141+ let startOffset = 0 ;
142+ let endOffset = 0 ;
112143 response ?. data ?. result ?. content ?. forEach ( element => {
144+ const currentMethod = element . Method ;
145+ const currentStartLine = Number ( element . StartLine ) ;
113146 if ( previousMethod && previousStartLine ) {
114- const start = new vscode . Position ( Number ( previousStartLine ) - 1 , 0 ) ;
115- const end = new vscode . Position ( Number ( element . StartLine ) - 2 , Number . MAX_VALUE ) ;
147+ const start = new vscode . Position ( previousStartLine - 1 + startOffset , 0 ) ;
148+ const end = new vscode . Position ( currentStartLine - 2 + endOffset , Number . MAX_VALUE ) ;
116149 detailedCoverage . push ( new vscode . DeclarationCoverage ( previousMethod , true , new vscode . Range ( start , end ) ) ) ;
117150 }
118- previousMethod = element . Method ;
119- previousStartLine = Number ( element . StartLine ) ;
151+ startOffset = endOffset ;
152+ endOffset = ( mapOffsets . get ( currentMethod ) || endOffset ) ;
153+ previousMethod = currentMethod ;
154+ previousStartLine = currentStartLine ;
120155 } ) ;
156+
157+ // Add the final method (if any)
121158 if ( previousMethod && previousStartLine ) {
122- const start = new vscode . Position ( Number ( previousStartLine ) - 1 , 0 ) ;
123- const end = new vscode . Position ( Number . MAX_VALUE , Number . MAX_VALUE ) ;
159+ const start = new vscode . Position ( previousStartLine - 1 + startOffset , 0 ) ;
160+ const end = new vscode . Position ( Number . MAX_VALUE , Number . MAX_VALUE ) ; // Hack that will cover the rest of the file, not just the the final method
124161 detailedCoverage . push ( new vscode . DeclarationCoverage ( previousMethod , true , new vscode . Range ( start , end ) ) ) ;
125162 }
126163 }
0 commit comments