bare-script 3.7.1 → 3.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,8 +15,8 @@ include <diff.bare>
15
15
 
16
16
 
17
17
  # Test statistics
18
- unittestTests = objectNew()
19
- unittestWarnings = arrayNew()
18
+ unittestTests = {}
19
+ unittestWarnings = []
20
20
 
21
21
 
22
22
  # $function: unittestRunTest
@@ -60,7 +60,7 @@ function unittestRunTestHelper(testName):
60
60
  endif
61
61
 
62
62
  # Add the unit test result array
63
- testFailures = arrayNew()
63
+ testFailures = []
64
64
  objectSet(unittestTests, testName, testFailures)
65
65
  systemGlobalSet('unittestTestName', testName)
66
66
 
@@ -81,7 +81,7 @@ function unittestEqual(actual, expected, description):
81
81
 
82
82
  # Add the test failure error lines
83
83
  testFailures = objectGet(unittestTests, unittestTestName)
84
- errorLines = arrayNew( \
84
+ errorLines = [ \
85
85
  'Equal:', \
86
86
  '', \
87
87
  '```', \
@@ -91,9 +91,9 @@ function unittestEqual(actual, expected, description):
91
91
  '```', \
92
92
  jsonStringify(expected), \
93
93
  '```' \
94
- )
94
+ ]
95
95
  if description:
96
- arrayPush(testFailures, arrayExtend(arrayNew(markdownEscape(description), ''), errorLines))
96
+ arrayPush(testFailures, arrayExtend([markdownEscape(description), ''], errorLines))
97
97
  else:
98
98
  arrayPush(testFailures, errorLines)
99
99
  endif
@@ -115,8 +115,8 @@ function unittestDeepEqual(actual, expected, description):
115
115
  endif
116
116
 
117
117
  # Compute the difference lines
118
- errorLines = arrayNew()
119
- diffErrorLines = arrayNew()
118
+ errorLines = []
119
+ diffErrorLines = []
120
120
  for diff in diffLines(actualJSON, expectedJSON):
121
121
  diffType = objectGet(diff, 'type')
122
122
  if diffType == 'Remove':
@@ -130,15 +130,15 @@ function unittestDeepEqual(actual, expected, description):
130
130
  else:
131
131
  # diffType == 'Identical'
132
132
  if diffErrorLines:
133
- arrayExtend(errorLines, arrayNew('Deep-equal:', '', '```'))
133
+ arrayExtend(errorLines, ['Deep-equal:', '', '```'])
134
134
  arrayExtend(errorLines, diffErrorLines)
135
135
  arrayPush(errorLines, '```')
136
- diffErrorLines = arrayNew()
136
+ diffErrorLines = []
137
137
  endif
138
138
  endif
139
139
  endfor
140
140
  if diffErrorLines:
141
- arrayExtend(errorLines, arrayNew('Deep-equal:', '', '```'))
141
+ arrayExtend(errorLines, ['Deep-equal:', '', '```'])
142
142
  arrayExtend(errorLines, diffErrorLines)
143
143
  arrayPush(errorLines, '```')
144
144
  endif
@@ -146,7 +146,7 @@ function unittestDeepEqual(actual, expected, description):
146
146
  # Add the test failure error lines
147
147
  testFailures = objectGet(unittestTests, unittestTestName)
148
148
  if description:
149
- arrayPush(testFailures, arrayExtend(arrayNew(markdownEscape(description), ''), errorLines))
149
+ arrayPush(testFailures, arrayExtend([markdownEscape(description), ''], errorLines))
150
150
  else:
151
151
  arrayPush(testFailures, errorLines)
152
152
  endif
@@ -210,7 +210,7 @@ function unittestReport(options):
210
210
  if testNameArg:
211
211
  markdownPrint('', argsLink(unittestReportArguments, 'All tests', null, true))
212
212
  else:
213
- markdownPrint('', argsLink(unittestReportArguments, if(hideTests, 'Show', 'Hide') + ' tests', objectNew('hideTests', !hideTests)))
213
+ markdownPrint('', argsLink(unittestReportArguments, if(hideTests, 'Show', 'Hide') + ' tests', {'hideTests': !hideTests}))
214
214
  endif
215
215
  endif
216
216
 
@@ -227,15 +227,15 @@ function unittestReport(options):
227
227
  if testFailCount:
228
228
  markdownPrint('', '## Failing Tests')
229
229
  if hideTests && !isReport && !testNameArg:
230
- markdownPrint('', argsLink(unittestReportArguments, 'Show', objectNew('hideTests', false)))
230
+ markdownPrint('', argsLink(unittestReportArguments, 'Show', {'hideTests': false}))
231
231
  endif
232
232
  if !hideTests || testNameArg:
233
233
  for testName in testNames:
234
234
  testFailures = objectGet(unittestTests, testName)
235
235
  if arrayLength(testFailures):
236
236
  failureLink = if(isReport, testName, \
237
- argsLink(unittestReportArguments, testName, objectNew('test', testName), false, '_top'))
238
- failureLines = arrayNew('', failureLink + ' - FAIL')
237
+ argsLink(unittestReportArguments, testName, {'test': testName}, false, '_top'))
238
+ failureLines = ['', failureLink + ' - FAIL']
239
239
  for errorLines in testFailures:
240
240
  for errorLine, ixErrorLine in errorLines:
241
241
  if ixErrorLine == 0:
@@ -256,14 +256,14 @@ function unittestReport(options):
256
256
  if testPassCount:
257
257
  markdownPrint('', '## Passing Tests')
258
258
  if hideTests && !isReport && !testNameArg:
259
- markdownPrint('', argsLink(unittestReportArguments, 'Show', objectNew('hideTests', false)))
259
+ markdownPrint('', argsLink(unittestReportArguments, 'Show', {'hideTests': false}))
260
260
  endif
261
261
  if !hideTests || testNameArg:
262
262
  for testName in testNames:
263
263
  testFailures = objectGet(unittestTests, testName)
264
264
  if !arrayLength(testFailures):
265
265
  testLink = if(isReport, testName, \
266
- argsLink(unittestReportArguments, testName, objectNew('test', testName), false, '_top'))
266
+ argsLink(unittestReportArguments, testName, {'test': testName}, false, '_top'))
267
267
  markdownPrint('', testLink + ' - OK')
268
268
  endif
269
269
  endfor
@@ -294,18 +294,18 @@ function unittestReport(options):
294
294
  for row in coverageData:
295
295
  scriptName = objectGet(row, 'Script')
296
296
  if !isReport && !stringStartsWith(scriptName, '**'):
297
- objectSet(row, 'Script', argsLink(unittestReportArguments, scriptName, objectNew("script", scriptName), false, "_top"))
297
+ objectSet(row, 'Script', argsLink(unittestReportArguments, scriptName, {"script": scriptName}, false, "_top"))
298
298
  endif
299
299
  objectSet(row, 'Coverage', numberToFixed(objectGet(row, 'Coverage'), 1) + '%')
300
300
  endfor
301
- markdownPrint('', dataTableMarkdown(coverageData, objectNew( \
302
- 'fields', arrayNew('Script', 'Statements', 'Missing', 'Coverage'), \
303
- 'formats', objectNew( \
304
- 'Statements', objectNew('align', 'right'), \
305
- 'Missing', objectNew('align', 'right'), \
306
- 'Coverage', objectNew('align', 'right') \
307
- ) \
308
- )))
301
+ markdownPrint('', dataTableMarkdown(coverageData, { \
302
+ 'fields': ['Script', 'Statements', 'Missing', 'Coverage'], \
303
+ 'formats': { \
304
+ 'Statements': {'align': 'right'}, \
305
+ 'Missing': {'align': 'right'}, \
306
+ 'Coverage': {'align': 'right'} \
307
+ } \
308
+ }))
309
309
  else:
310
310
  markdownPrint('', '*No data.*')
311
311
  endif
@@ -317,12 +317,12 @@ endfunction
317
317
 
318
318
 
319
319
  # unittestReport application arguments
320
- unittestReportArguments = argsValidate(arrayNew( \
321
- objectNew('name', 'test', 'global', 'vUnittestTest'), \
322
- objectNew('name', 'script', 'global', 'vUnittestScript'), \
323
- objectNew('name', 'hideTests', 'global', 'vUnittestHideTests', 'type', 'bool', 'default', false), \
324
- objectNew('name', 'report', 'global', 'vUnittestReport', 'type', 'bool', 'default', false) \
325
- ))
320
+ unittestReportArguments = argsValidate([ \
321
+ {'name': 'test', 'global': 'vUnittestTest'}, \
322
+ {'name': 'script', 'global': 'vUnittestScript'}, \
323
+ {'name': 'hideTests', 'global': 'vUnittestHideTests', 'type': 'bool', 'default': false}, \
324
+ {'name': 'report', 'global': 'vUnittestReport', 'type': 'bool', 'default': false} \
325
+ ])
326
326
 
327
327
 
328
328
  # Render the script coverage details page
@@ -331,7 +331,7 @@ function unittestReportScript(scriptName):
331
331
  title = scriptName + ' Coverage'
332
332
  documentSetTitle(title)
333
333
  markdownPrint( \
334
- argsLink(unittestReportArguments, 'Back', objectNew('script', null), false, '_top'), \
334
+ argsLink(unittestReportArguments, 'Back', {'script': null}, false, '_top'), \
335
335
  '', \
336
336
  '# ' + markdownEscape(title) \
337
337
  )
@@ -349,7 +349,7 @@ function unittestReportScript(scriptName):
349
349
  scriptLines = objectGet(script, 'scriptLines')
350
350
 
351
351
  # Mark the statements covered or not-covered
352
- lineColors = objectNew()
352
+ lineColors = {}
353
353
  statements = unittestScriptStatements(script)
354
354
  for statement in statements:
355
355
  statementKey = arrayGet(objectKeys(statement), 0)
@@ -369,9 +369,9 @@ function unittestReportScript(scriptName):
369
369
  endfor
370
370
 
371
371
  # Generate the code coverage details
372
- codeLineElements = arrayNew()
373
- codeElements = objectNew('html', 'pre', 'elem', codeLineElements)
374
- currentLines = arrayNew()
372
+ codeLineElements = []
373
+ codeElements = {'html': 'pre', 'elem': codeLineElements}
374
+ currentLines = []
375
375
  currentColor = null
376
376
  for line, ixLine in scriptLines:
377
377
  # Accumulate lines of the same color
@@ -383,7 +383,7 @@ function unittestReportScript(scriptName):
383
383
 
384
384
  # Render the current lines
385
385
  unittestReportScriptLines(codeLineElements, currentLines, currentColor)
386
- currentLines = arrayNew(line)
386
+ currentLines = [line]
387
387
  currentColor = lineColor
388
388
  endfor
389
389
  unittestReportScriptLines(codeLineElements, currentLines, currentColor, true)
@@ -395,13 +395,13 @@ function unittestReportScriptLines(codeLineElements, lines, color, noNewline):
395
395
  if lines:
396
396
  linesStr = arrayJoin(lines, stringFromCharCode(10)) + if(noNewline, '', stringFromCharCode(10))
397
397
  if !color:
398
- arrayPush(codeLineElements, objectNew('text', linesStr))
398
+ arrayPush(codeLineElements, {'text': linesStr})
399
399
  else:
400
- arrayPush(codeLineElements, objectNew( \
401
- 'html', 'span', \
402
- 'attr', objectNew('style', 'display: block; background-color: ' + color), \
403
- 'elem', objectNew('text', linesStr) \
404
- ))
400
+ arrayPush(codeLineElements, { \
401
+ 'html': 'span', \
402
+ 'attr': {'style': 'display: block; background-color: ' + color}, \
403
+ 'elem': {'text': linesStr} \
404
+ })
405
405
  endif
406
406
  endif
407
407
  endfunction
@@ -409,14 +409,14 @@ endfunction
409
409
 
410
410
  # Get the coverage data table - columns are "Script", "Statement", "Covered", and "Percent"
411
411
  function unittestCoverageData(coverageExclude):
412
- data = arrayNew()
412
+ data = []
413
413
 
414
414
  # Get the global coverage object
415
415
  coverage = coverageGlobalGet()
416
416
  if coverage:
417
417
  # Get the script names with coverage data
418
418
  scripts = objectGet(coverage, 'scripts')
419
- scriptNames = if(scripts, arraySort(objectKeys(scripts)), arrayNew())
419
+ scriptNames = if(scripts, arraySort(objectKeys(scripts)), [])
420
420
 
421
421
  # Compute script statement coverage
422
422
  totalStatements = 0
@@ -458,25 +458,25 @@ function unittestCoverageData(coverageExclude):
458
458
 
459
459
  # Add the script coverage data row
460
460
  coveragePercent = if(statementCount, 100 * (statementCount - missingCount) / statementCount, 100)
461
- arrayPush(data, objectNew( \
462
- 'Script', scriptName, \
463
- 'Statements', statementCount, \
464
- 'Missing', missingCount, \
465
- 'Coverage', coveragePercent, \
466
- 'CoverageStr', numberToFixed(coveragePercent, 1) + '%' \
467
- ))
461
+ arrayPush(data, { \
462
+ 'Script': scriptName, \
463
+ 'Statements': statementCount, \
464
+ 'Missing': missingCount, \
465
+ 'Coverage': coveragePercent, \
466
+ 'CoverageStr': numberToFixed(coveragePercent, 1) + '%' \
467
+ })
468
468
  endfor
469
469
 
470
470
  # Add the coverage totals data row
471
471
  if scriptNames:
472
472
  coveragePercent = if(totalStatements, 100 * (totalStatements - totalMissing) / totalStatements, 100)
473
- arrayPush(data, objectNew( \
474
- 'Script', '**Total**', \
475
- 'Statements', totalStatements, \
476
- 'Missing', totalMissing, \
477
- 'Coverage', coveragePercent, \
478
- 'CoverageStr', numberToFixed(coveragePercent, 1) + '%' \
479
- ))
473
+ arrayPush(data, { \
474
+ 'Script': '**Total**', \
475
+ 'Statements': totalStatements, \
476
+ 'Missing': totalMissing, \
477
+ 'Coverage': coveragePercent, \
478
+ 'CoverageStr': numberToFixed(coveragePercent, 1) + '%' \
479
+ })
480
480
  endif
481
481
  endif
482
482
 
@@ -486,7 +486,7 @@ endfunction
486
486
 
487
487
  # Get a script's array of statements
488
488
  function unittestScriptStatements(script):
489
- statements = arrayNew()
489
+ statements = []
490
490
 
491
491
  # Add the top-level script statements
492
492
  for statement in objectGet(script, 'statements'):
@@ -18,16 +18,16 @@ unittestMockWindowWidth = 1024
18
18
 
19
19
 
20
20
  # The mocked MarkdownUp state
21
- unittestMockCalls = arrayNew()
22
- unittestMockFunctions = objectNew()
23
- unittestMockStateDefault = objectNew( \
24
- 'drawingFontSizePx', unittestMockDefaultFontSizePx, \
25
- 'drawingHeight', 480, \
26
- 'drawingWidth', 640, \
27
- 'localStorage', objectNew(), \
28
- 'sessionStorage', objectNew(), \
29
- 'windowClipboard', '' \
30
- )
21
+ unittestMockCalls = []
22
+ unittestMockFunctions = {}
23
+ unittestMockStateDefault = { \
24
+ 'drawingFontSizePx': unittestMockDefaultFontSizePx, \
25
+ 'drawingHeight': 480, \
26
+ 'drawingWidth': 640, \
27
+ 'localStorage': {}, \
28
+ 'sessionStorage': {}, \
29
+ 'windowClipboard': '' \
30
+ }
31
31
  unittestMockState = objectCopy(unittestMockStateDefault)
32
32
 
33
33
 
@@ -145,7 +145,7 @@ endfunction
145
145
 
146
146
  function unittestMockGeneric(funcName, args...):
147
147
  # Record the mocked function call
148
- arrayPush(unittestMockCalls, arrayNew(funcName, args))
148
+ arrayPush(unittestMockCalls, [funcName, args])
149
149
  endfunction
150
150
 
151
151
 
@@ -161,8 +161,8 @@ function unittestMockEnd():
161
161
 
162
162
  # Reset the mock state
163
163
  mockCalls = unittestMockCalls
164
- systemGlobalSet('unittestMockCalls', arrayNew())
165
- systemGlobalSet('unittestMockFunctions', objectNew())
164
+ systemGlobalSet('unittestMockCalls', [])
165
+ systemGlobalSet('unittestMockFunctions', {})
166
166
  systemGlobalSet('unittestMockState', objectCopy(unittestMockStateDefault))
167
167
 
168
168
  return mockCalls
@@ -183,7 +183,7 @@ function unittestMock_documentInputValue(data, args...):
183
183
  id = arrayGet(args, 0)
184
184
 
185
185
  # Record the mocked function call
186
- arrayPush(unittestMockCalls, arrayNew('documentInputValue', args))
186
+ arrayPush(unittestMockCalls, ['documentInputValue', args])
187
187
 
188
188
  # Return the mocked documentInputValue response
189
189
  return if(data != null, objectGet(data, id))
@@ -210,7 +210,7 @@ function unittestMock_drawNew(args...):
210
210
  height = arrayGet(args, 1)
211
211
 
212
212
  # Record the mocked function call
213
- arrayPush(unittestMockCalls, arrayNew('drawNew', args))
213
+ arrayPush(unittestMockCalls, ['drawNew', args])
214
214
 
215
215
  # Update the mock state
216
216
  objectSet(unittestMockState, 'drawingWidth', width)
@@ -230,7 +230,7 @@ function unittestMock_drawTextStyle(args...):
230
230
  fontSizePx = arrayGet(args, 0)
231
231
 
232
232
  # Record the mocked function call
233
- arrayPush(unittestMockCalls, arrayNew('drawTextStyle', args))
233
+ arrayPush(unittestMockCalls, ['drawTextStyle', args])
234
234
 
235
235
  # Update the mock state
236
236
  objectSet(unittestMockState, 'drawingFontSizePx', if(fontSizePx != null, fontSizePx, unittestMockDefaultFontSizePx))
@@ -254,10 +254,10 @@ endfunction
254
254
 
255
255
  function unittestMock_localStorageClear(args...):
256
256
  # Record the mocked function call
257
- arrayPush(unittestMockCalls, arrayNew('localStorageClear', args))
257
+ arrayPush(unittestMockCalls, ['localStorageClear', args])
258
258
 
259
259
  # Update the mock state
260
- objectSet(unittestMockState, 'localStorage', objectNew())
260
+ objectSet(unittestMockState, 'localStorage', {})
261
261
  endfunction
262
262
 
263
263
 
@@ -270,7 +270,7 @@ function unittestMock_localStorageRemove(args...):
270
270
  key = arrayGet(args, 0)
271
271
 
272
272
  # Record the mocked function call
273
- arrayPush(unittestMockCalls, arrayNew('localStorageRemove', args))
273
+ arrayPush(unittestMockCalls, ['localStorageRemove', args])
274
274
 
275
275
  # Update the mock state
276
276
  objectDelete(objectGet(unittestMockState, 'localStorage'), key)
@@ -282,7 +282,7 @@ function unittestMock_localStorageSet(args...):
282
282
  value = arrayGet(args, 1)
283
283
 
284
284
  # Record the mocked function call
285
- arrayPush(unittestMockCalls, arrayNew('localStorageSet', args))
285
+ arrayPush(unittestMockCalls, ['localStorageSet', args])
286
286
 
287
287
  # Update the mock state
288
288
  objectSet(objectGet(unittestMockState, 'localStorage'), key, value)
@@ -317,7 +317,7 @@ unittestMock_markdownHeaderId_dash = regexNew('[^a-z0-9]+')
317
317
 
318
318
  function unittestMock_markdownParse(data, args...):
319
319
  # Record the mocked function call
320
- arrayPush(unittestMockCalls, arrayNew('markdownParse', args))
320
+ arrayPush(unittestMockCalls, ['markdownParse', args])
321
321
 
322
322
  # Return the mocked markdownParse response
323
323
  return if(data != null, arrayShift(data))
@@ -326,7 +326,7 @@ endfunction
326
326
 
327
327
  function unittestMock_markdownTitle(data, args...):
328
328
  # Record the mocked function call
329
- arrayPush(unittestMockCalls, arrayNew('markdownTitle', args))
329
+ arrayPush(unittestMockCalls, ['markdownTitle', args])
330
330
 
331
331
  # Return the mocked markdownTitle response
332
332
  return if(data != null, arrayShift(data))
@@ -344,11 +344,11 @@ function unittestMock_schemaElements(types, typeName):
344
344
  if userTypeKey == 'struct' && objectGet(objectGet(userType, 'struct'), 'union'):
345
345
  userTypeKey = 'union'
346
346
  endif
347
- return arrayNew( \
348
- arrayNew( \
349
- objectNew('html', 'h1', 'elem', objectNew('text', userTypeKey + ' ' + typeName)) \
350
- ) \
351
- )
347
+ return [ \
348
+ [ \
349
+ {'html': 'h1', 'elem': {'text': userTypeKey + ' ' + typeName}} \
350
+ ] \
351
+ ]
352
352
  endfunction
353
353
 
354
354
 
@@ -359,10 +359,10 @@ endfunction
359
359
 
360
360
  function unittestMock_sessionStorageClear(args...):
361
361
  # Record the mocked function call
362
- arrayPush(unittestMockCalls, arrayNew('sessionStorageClear', args))
362
+ arrayPush(unittestMockCalls, ['sessionStorageClear', args])
363
363
 
364
364
  # Update the mock state
365
- objectSet(unittestMockState, 'sessionStorage', objectNew())
365
+ objectSet(unittestMockState, 'sessionStorage', {})
366
366
  endfunction
367
367
 
368
368
 
@@ -375,7 +375,7 @@ function unittestMock_sessionStorageRemove(args...):
375
375
  key = arrayGet(args, 0)
376
376
 
377
377
  # Record the mocked function call
378
- arrayPush(unittestMockCalls, arrayNew('sessionStorageRemove', args))
378
+ arrayPush(unittestMockCalls, ['sessionStorageRemove', args])
379
379
 
380
380
  # Update the mock state
381
381
  objectDelete(objectGet(unittestMockState, 'sessionStorage'), key)
@@ -387,7 +387,7 @@ function unittestMock_sessionStorageSet(args...):
387
387
  value = arrayGet(args, 1)
388
388
 
389
389
  # Record the mocked function call
390
- arrayPush(unittestMockCalls, arrayNew('sessionStorageSet', args))
390
+ arrayPush(unittestMockCalls, ['sessionStorageSet', args])
391
391
 
392
392
  # Update the mock state
393
393
  objectSet(objectGet(unittestMockState, 'sessionStorage'), key, value)
@@ -403,12 +403,12 @@ function unittestMock_systemFetch(data, args...):
403
403
  url = arrayGet(args, 0)
404
404
 
405
405
  # Record the mocked function call
406
- arrayPush(unittestMockCalls, arrayNew('systemFetch', args))
406
+ arrayPush(unittestMockCalls, ['systemFetch', args])
407
407
 
408
408
  # Array of URLs?
409
409
  urlType = systemType(url)
410
410
  if urlType == 'array':
411
- result = arrayNew()
411
+ result = []
412
412
  for urlItem in url:
413
413
  urlActual = if(systemType(urlItem) == 'object', objectGet(urlItem, 'url'), urlItem)
414
414
  arrayPush(result, if(data != null, objectGet(data, urlActual)))
@@ -446,7 +446,7 @@ function unittestMock_windowClipboardWrite(args...):
446
446
  text = arrayGet(args, 0)
447
447
 
448
448
  # Record the mocked function call
449
- arrayPush(unittestMockCalls, arrayNew('windowClipboardWrite', args))
449
+ arrayPush(unittestMockCalls, ['windowClipboardWrite', args])
450
450
 
451
451
  # Update the mock state
452
452
  objectSet(unittestMockState, 'windowClipboard', text)
package/lib/model.js CHANGED
@@ -324,21 +324,20 @@ export function validateExpression(expr) {
324
324
  */
325
325
  export function lintScript(script) {
326
326
  const warnings = [];
327
+ const {statements} = script;
327
328
 
328
329
  // Empty script?
329
- if (script.statements.length === 0) {
330
- warnings.push('Empty script');
330
+ if (statements.length === 0) {
331
+ lintScriptWarning(warnings, script, null, 'Empty script');
331
332
  }
332
333
 
333
334
  // Variable used before assignment?
334
335
  const varAssigns = {};
335
336
  const varUses = {};
336
- getVariableAssignmentsAndUses(script.statements, varAssigns, varUses);
337
+ getVariableAssignmentsAndUses(statements, varAssigns, varUses);
337
338
  for (const varName of Object.keys(varAssigns)) {
338
339
  if (varName in varUses && varUses[varName] <= varAssigns[varName]) {
339
- warnings.push(
340
- `Global variable "${varName}" used (index ${varUses[varName]}) before assignment (index ${varAssigns[varName]})`
341
- );
340
+ lintScriptWarning(warnings, script, statements[varUses[varName]], `Global variable "${varName}" used before assignment`);
342
341
  }
343
342
  }
344
343
 
@@ -346,14 +345,14 @@ export function lintScript(script) {
346
345
  const functionsDefined = {};
347
346
  const labelsDefined = {};
348
347
  const labelsUsed = {};
349
- for (const [ixStatement, statement] of script.statements.entries()) {
348
+ for (const [ixStatement, statement] of statements.entries()) {
350
349
  const [statementKey] = Object.keys(statement);
351
350
 
352
351
  // Function definition checks
353
352
  if (statementKey === 'function') {
354
353
  // Function redefinition?
355
354
  if (statement.function.name in functionsDefined) {
356
- warnings.push(`Redefinition of function "${statement.function.name}" (index ${ixStatement})`);
355
+ lintScriptWarning(warnings, script, statement, `Redefinition of function "${statement.function.name}"`);
357
356
  } else {
358
357
  functionsDefined[statement.function.name] = ixStatement;
359
358
  }
@@ -369,9 +368,9 @@ export function lintScript(script) {
369
368
  continue;
370
369
  }
371
370
  if (varName in fnVarUses && fnVarUses[varName] <= fnVarAssigns[varName]) {
372
- warnings.push(
373
- `Variable "${varName}" of function "${statement.function.name}" used (index ${fnVarUses[varName]}) ` +
374
- `before assignment (index ${fnVarAssigns[varName]})`
371
+ lintScriptWarning(
372
+ warnings, script, statement,
373
+ `Variable "${varName}" of function "${statement.function.name}" used before assignment`
375
374
  );
376
375
  }
377
376
  }
@@ -379,8 +378,9 @@ export function lintScript(script) {
379
378
  // Unused variables?
380
379
  for (const varName of Object.keys(fnVarAssigns)) {
381
380
  if (!(varName in fnVarUses)) {
382
- warnings.push(
383
- `Unused variable "${varName}" defined in function "${statement.function.name}" (index ${fnVarAssigns[varName]})`
381
+ lintScriptWarning(
382
+ warnings, script, statement,
383
+ `Unused variable "${varName}" defined in function "${statement.function.name}"`
384
384
  );
385
385
  }
386
386
  }
@@ -391,13 +391,17 @@ export function lintScript(script) {
391
391
  for (const arg of args) {
392
392
  // Duplicate argument?
393
393
  if (argsDefined.has(arg)) {
394
- warnings.push(`Duplicate argument "${arg}" of function "${statement.function.name}" (index ${ixStatement})`);
394
+ lintScriptWarning(
395
+ warnings, script, statement, `Duplicate argument "${arg}" of function "${statement.function.name}"`
396
+ );
395
397
  } else {
396
398
  argsDefined.add(arg);
397
399
 
398
400
  // Unused argument?
399
401
  if (!(arg in fnVarUses)) {
400
- warnings.push(`Unused argument "${arg}" of function "${statement.function.name}" (index ${ixStatement})`);
402
+ lintScriptWarning(
403
+ warnings, script, statement, `Unused argument "${arg}" of function "${statement.function.name}"`
404
+ );
401
405
  }
402
406
  }
403
407
  }
@@ -413,7 +417,7 @@ export function lintScript(script) {
413
417
  if (fnStatementKey === 'expr') {
414
418
  // Pointless function expression statement?
415
419
  if (!('name' in fnStatement.expr) && isPointlessExpression(fnStatement.expr.expr)) {
416
- warnings.push(`Pointless statement in function "${statement.function.name}" (index ${ixFnStatement})`);
420
+ lintScriptWarning(warnings, script, statement, `Pointless statement in function "${statement.function.name}"`);
417
421
  }
418
422
 
419
423
  // Function label statement checks
@@ -421,8 +425,9 @@ export function lintScript(script) {
421
425
  // Label redefinition?
422
426
  const fnStatementLabel = fnStatement.label.name;
423
427
  if (fnStatementLabel in fnLabelsDefined) {
424
- warnings.push(
425
- `Redefinition of label "${fnStatementLabel}" in function "${statement.function.name}" (index ${ixFnStatement})`
428
+ lintScriptWarning(
429
+ warnings, script, statement,
430
+ `Redefinition of label "${fnStatementLabel}" in function "${statement.function.name}"`
426
431
  );
427
432
  } else {
428
433
  fnLabelsDefined[fnStatementLabel] = ixFnStatement;
@@ -439,14 +444,14 @@ export function lintScript(script) {
439
444
  // Unused function labels?
440
445
  for (const label of Object.keys(fnLabelsDefined)) {
441
446
  if (!(label in fnLabelsUsed)) {
442
- warnings.push(`Unused label "${label}" in function "${statement.function.name}" (index ${fnLabelsDefined[label]})`);
447
+ lintScriptWarning(warnings, script, statement, `Unused label "${label}" in function "${statement.function.name}"`);
443
448
  }
444
449
  }
445
450
 
446
451
  // Unknown function labels?
447
452
  for (const label of Object.keys(fnLabelsUsed)) {
448
453
  if (!(label in fnLabelsDefined)) {
449
- warnings.push(`Unknown label "${label}" in function "${statement.function.name}" (index ${fnLabelsUsed[label]})`);
454
+ lintScriptWarning(warnings, script, statement, `Unknown label "${label}" in function "${statement.function.name}"`);
450
455
  }
451
456
  }
452
457
 
@@ -454,7 +459,7 @@ export function lintScript(script) {
454
459
  } else if (statementKey === 'expr') {
455
460
  // Pointless global expression statement?
456
461
  if (!('name' in statement.expr) && isPointlessExpression(statement.expr.expr)) {
457
- warnings.push(`Pointless global statement (index ${ixStatement})`);
462
+ lintScriptWarning(warnings, script, statement, 'Pointless global statement');
458
463
  }
459
464
 
460
465
  // Global label statement checks
@@ -462,7 +467,7 @@ export function lintScript(script) {
462
467
  // Label redefinition?
463
468
  const statementLabel = statement.label.name;
464
469
  if (statementLabel in labelsDefined) {
465
- warnings.push(`Redefinition of global label "${statementLabel}" (index ${ixStatement})`);
470
+ lintScriptWarning(warnings, script, statement, `Redefinition of global label "${statementLabel}"`);
466
471
  } else {
467
472
  labelsDefined[statementLabel] = ixStatement;
468
473
  }
@@ -478,14 +483,14 @@ export function lintScript(script) {
478
483
  // Unused global labels?
479
484
  for (const label of Object.keys(labelsDefined)) {
480
485
  if (!(label in labelsUsed)) {
481
- warnings.push(`Unused global label "${label}" (index ${labelsDefined[label]})`);
486
+ lintScriptWarning(warnings, script, statements[labelsDefined[label]], `Unused global label "${label}"`);
482
487
  }
483
488
  }
484
489
 
485
490
  // Unknown global labels?
486
491
  for (const label of Object.keys(labelsUsed)) {
487
492
  if (!(label in labelsDefined)) {
488
- warnings.push(`Unknown global label "${label}" (index ${labelsUsed[label]})`);
493
+ lintScriptWarning(warnings, script, statements[labelsUsed[label]], `Unknown global label "${label}"`);
489
494
  }
490
495
  }
491
496
 
@@ -493,6 +498,21 @@ export function lintScript(script) {
493
498
  }
494
499
 
495
500
 
501
+ // Helper to format static analysis warnings
502
+ function lintScriptWarning(warnings, script, statement, message) {
503
+ let warning;
504
+ if (script && statement) {
505
+ const [statementKey] = Object.keys(statement);
506
+ const scriptName = script.scriptName ?? '';
507
+ const lineno = statement[statementKey].lineNumber ?? '';
508
+ warning = (scriptName || lineno) ? `${scriptName}:${lineno}: ${message}` : message;
509
+ } else {
510
+ warning = message;
511
+ }
512
+ warnings.push(warning);
513
+ }
514
+
515
+
496
516
  // Helper function to determine if an expression statement's expression is pointless
497
517
  function isPointlessExpression(expr) {
498
518
  const [exprKey] = Object.keys(expr);