• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

polserver / polserver / 21100551564

17 Jan 2026 08:40PM UTC coverage: 60.504% (+0.01%) from 60.492%
21100551564

Pull #857

github

turleypol
fixed scope
Pull Request #857: ClangTidy readability-else-after-return

837 of 1874 new or added lines in 151 files covered. (44.66%)

48 existing lines in 26 files now uncovered.

44445 of 73458 relevant lines covered (60.5%)

515341.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.54
/pol-core/bscript/compiler/file/PrettifyFileProcessor.cpp
1
#include "PrettifyFileProcessor.h"
2

3
#include "bscript/compiler/Profile.h"
4
#include "bscript/compiler/Report.h"
5
#include "bscript/compiler/ast/Statement.h"
6
#include "bscript/compiler/file/PrettifyLineBuilder.h"
7
#include "bscript/compiler/file/SourceFile.h"
8
#include "bscript/compiler/file/SourceFileIdentifier.h"
9
#include "bscript/compilercfg.h"
10
#include "clib/filecont.h"
11
#include "clib/logfacility.h"
12

13
#include <algorithm>
14
#include <any>
15
#include <iostream>
16
#include <memory>
17
#include <utility>
18
#include <vector>
19

20
/*
21
  //LineWidth
22
  FormatterLineWidth 100
23
  // keep original keyword spelling
24
  FormatterKeepKeywords 0
25
  // number of spaces for indent
26
  FormatterIndentLevel 2
27
  // multiple newlines get merged to a single
28
  FormatterMergeEmptyLines 1
29
  // space between emtpy parenthesis eg foo() vs foo( )
30
  FormatterEmptyParenthesisSpacing 0
31
  // space between emtpy brackets eg struct{} vs struct{ }
32
  FormatterEmptyBracketSpacing 0
33
  // space after/before parenthesis in conditionals
34
  // eg if ( true ) vs if (true)
35
  FormatterConditionalParenthesisSpacing 1
36
  // space after/before parenthesis
37
  // eg foo( true ) vs foo(true)
38
  FormatterParenthesisSpacing 1
39
  // space after/before brackets
40
  // eg array{ true } vs array{true}
41
  FormatterBracketSpacing 1
42
  // no space between type and opening brackect
43
  // eg struct{} vs struct {}
44
  FormatterBracketAttachToType 1
45
  // add space after delimiter comma or semi in for loops
46
  // eg {1, 2, 3} vs {1,2,3}
47
  FormatterDelimiterSpacing 1
48
  // add space around assignment
49
  // eg a := 1; vs a:=1;
50
  FormatterAssignmentSpacing 1
51
  // add space around comparison
52
  // eg a == 1 vs a==1
53
  FormatterComparisonSpacing 1
54
  // add space around operations
55
  // eg a + 1 vs a+1
56
  FormatterEllipsisSpacing 0
57
  // add space before ellipsis (...)
58
  // eg a... vs a ...
59
  FormatterOperatorSpacing 1
60
  // use \r\n as newline instead of \n
61
  FormatterWindowsLineEndings 0
62
  // use tabs instead of spaces
63
  FormatterUseTabs 0
64
  // tab width
65
  FormatterTabWidth 4
66
  // Insert a newline at end of file if missing
67
  FormatterInsertNewlineAtEOF 1
68
  // align trailing comments in a statement
69
  FormatterAlignTrailingComments 1
70
  // short case labels will be contracted to a single line
71
  FormatterAllowShortCaseLabelsOnASingleLine 1
72
  // short function references will be contracted to a single line
73
  FormatterAllowShortFuncRefsOnASingleLine 1
74
  // align short case statements needs FormatterAllowShortCaseLabelsOnASingleLine
75
  FormatterAlignConsecutiveShortCaseStatements 1
76
*/
77

78
namespace Pol::Bscript::Compiler
79
{
80
using namespace EscriptGrammar;
81

82
PrettifyFileProcessor::PrettifyFileProcessor( const SourceFileIdentifier& source_file_identifier,
660✔
83
                                              Profile& /*profile*/, Report& report )
660✔
84
    : source_file_identifier( source_file_identifier ) /*, profile( profile )*/, report( report )
660✔
85
{
86
}
660✔
87

88
antlrcpp::Any PrettifyFileProcessor::process_compilation_unit( SourceFile& sf )
660✔
89
{
90
  if ( auto compilation_unit = sf.get_compilation_unit( report, source_file_identifier ) )
660✔
91
  {
92
    if ( report.error_count() )
660✔
93
      return {};
×
94
    preprocess( sf );
660✔
95
    return compilation_unit->accept( this );
660✔
96
  }
97
  throw std::runtime_error( "No compilation unit in source file" );
×
98
}
99

100
antlrcpp::Any PrettifyFileProcessor::process_module_unit( SourceFile& sf )
×
101
{
102
  if ( auto module_unit = sf.get_module_unit( report, source_file_identifier ) )
×
103
  {
104
    if ( report.error_count() )
×
105
      return {};
×
106
    preprocess( sf );
×
107
    return module_unit->accept( this );
×
108
  }
109
  throw std::runtime_error( "No compilation unit in source file" );
×
110
}
111

112
antlrcpp::Any PrettifyFileProcessor::visitCompilationUnit(
660✔
113
    EscriptParser::CompilationUnitContext* ctx )
114
{
115
  visitChildren( ctx );
660✔
116
  if ( !linebuilder.finalize() )
660✔
117
    report.error( source_file_identifier, "left over formatting lines: {}",
×
118
                  linebuilder.currentTokens() );
119
  return {};
660✔
120
}
121

122
antlrcpp::Any PrettifyFileProcessor::visitModuleUnit( EscriptParser::ModuleUnitContext* ctx )
×
123
{
124
  visitChildren( ctx );
×
125
  if ( !linebuilder.finalize() )
×
126
    report.error( source_file_identifier, "left over formatting lines: {}",
×
127
                  linebuilder.currentTokens() );
128
  return {};
×
129
}
130

131

132
std::string PrettifyFileProcessor::prettify() const
660✔
133
{
134
  auto result =
135
      fmt::format( "{}", fmt::join( linebuilder.formattedLines(),
1,320✔
136
                                    compilercfg.FormatterWindowsLineEndings ? "\r\n" : "\n" ) );
1,320✔
137
  if ( result.empty() )
660✔
138
  {
139
    report.error( source_file_identifier, "formatting result is empty" );
×
140
    return {};
×
141
  }
142
  if ( compilercfg.FormatterInsertNewlineAtEOF && !result.empty() && result.back() != '\n' )
660✔
143
    result += compilercfg.FormatterWindowsLineEndings ? "\r\n" : "\n";
655✔
144
  return result;
660✔
145
}
660✔
146

147

148
antlrcpp::Any PrettifyFileProcessor::visitVarStatement( EscriptParser::VarStatementContext* ctx )
897✔
149
{
150
  _currentscope |= FmtToken::Scope::VAR;
897✔
151
  addToken( "var", ctx->VAR(), FmtToken::SPACE, FmtContext::VAR_STATEMENT );
897✔
152
  visitVariableDeclarationList( ctx->variableDeclarationList() );
897✔
153
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
897✔
154
  _currentscope &= ~FmtToken::Scope::VAR;
897✔
155
  linebuilder.buildLine( _currindent );
897✔
156
  return {};
897✔
157
}
158

159
antlrcpp::Any PrettifyFileProcessor::visitParExpression( EscriptParser::ParExpressionContext* ctx )
460✔
160
{
161
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle() & ~FmtToken::ATTACHED );
460✔
162
  auto args = std::any_cast<bool>( visitExpression( ctx->expression() ) );
460✔
163
  addToken( ")", ctx->RPAREN(), linebuilder.closingParenthesisStyle( args ) );
460✔
164
  return {};
460✔
165
}
166

167
antlrcpp::Any PrettifyFileProcessor::visitBlock( EscriptParser::BlockContext* ctx )
1,243✔
168
{
169
  ++_currindent;
1,243✔
170
  visitChildren( ctx );
1,243✔
171
  --_currindent;
1,243✔
172
  return {};
1,243✔
173
}
174
antlrcpp::Any PrettifyFileProcessor::visitWhileStatement(
45✔
175
    EscriptParser::WhileStatementContext* ctx )
176
{
177
  make_statement_label( ctx->statementLabel() );
45✔
178
  addToken( "while", ctx->WHILE(), FmtToken::SPACE );
45✔
179
  visitParExpression( ctx->parExpression() );
45✔
180
  linebuilder.buildLine( _currindent );
45✔
181

182
  visitBlock( ctx->block() );
45✔
183
  addToken( "endwhile", ctx->ENDWHILE(), FmtToken::SPACE );
45✔
184
  linebuilder.buildLine( _currindent );
45✔
185
  return {};
45✔
186
}
187

188
antlrcpp::Any PrettifyFileProcessor::visitVariableDeclarationList(
897✔
189
    EscriptParser::VariableDeclarationListContext* ctx )
190
{
191
  auto args = ctx->variableDeclaration();
897✔
192
  for ( size_t i = 0; i < args.size(); ++i )
1,867✔
193
  {
194
    visitVariableDeclaration( args[i] );
970✔
195
    if ( i < args.size() - 1 )
970✔
196
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle(), FmtContext::VAR_COMMA );
73✔
197
  }
198
  return {};
1,794✔
199
}
897✔
200
antlrcpp::Any PrettifyFileProcessor::visitVariableDeclaration(
970✔
201
    EscriptParser::VariableDeclarationContext* ctx )
202
{
203
  if ( auto identifier = ctx->IDENTIFIER() )
970✔
204
  {
205
    make_identifier( identifier );
925✔
206

207
    if ( auto variable_declaration_initializer = ctx->variableDeclarationInitializer() )
925✔
208
    {
209
      _currentscope |= FmtToken::Scope::VAR;
775✔
210

211
      if ( auto assign = variable_declaration_initializer->ASSIGN() )
775✔
212
        addToken( ":=", assign, linebuilder.assignmentStyle() );
752✔
213

214
      if ( auto expression = variable_declaration_initializer->expression() )
775✔
215
        visitExpression( expression );
752✔
216
      else if ( auto arr = variable_declaration_initializer->ARRAY() )
23✔
217
        addToken( "array", arr, FmtToken::SPACE );
23✔
218
      _currentscope &= ~FmtToken::Scope::VAR;
775✔
219
    }
220
  }
221
  else if ( ctx->bindingDeclaration() )
45✔
222
  {
223
    _currentscope |= FmtToken::Scope::VAR;
45✔
224
    visitChildren( ctx );
45✔
225
    _currentscope &= ~FmtToken::Scope::VAR;
45✔
226
  }
227

228
  return {};
970✔
229
}
230

231
antlrcpp::Any PrettifyFileProcessor::visitBindingDeclaration(
59✔
232
    EscriptGrammar::EscriptParser::BindingDeclarationContext* ctx )
233
{
234
  // If the preceeding token is VAR or COMMA, we need to force unattached, ie:
235
  //   `var [foo]` (FormatterBracketSpacing=0), and
236
  //   `var [ foo ]` (FormatterBracketSpacing=1),
237
  // the LBRACK must not be attached.
238
  auto const& last_token = linebuilder.currentTokens().back();
59✔
239
  bool force_unattached =
59✔
240
      last_token.token_type == EscriptLexer::VAR || last_token.token_type == EscriptLexer::COMMA ||
69✔
241
      ( last_token.token_type == EscriptLexer::COLON && compilercfg.FormatterAssignmentSpacing );
10✔
242

243
  if ( auto lbrack = ctx->LBRACK() )
59✔
244
  {
245
    addToken( "[", lbrack, linebuilder.openingBracketStyle( false, force_unattached ) );
33✔
246
    ++_currentgroup;
33✔
247
    _currentscope |= FmtToken::Scope::ARRAY;
33✔
248
    size_t curcount = linebuilder.currentTokens().size();
33✔
249
    visitSequenceBindingList( ctx->sequenceBindingList() );
33✔
250
    _currentscope &= ~FmtToken::Scope::ARRAY;
33✔
251
    --_currentgroup;
33✔
252
    addToken( "]", ctx->RBRACK(),
33✔
253
              linebuilder.closingBracketStyle( curcount ) & ~FmtToken::BREAKPOINT );
33✔
254
  }
255
  else if ( auto lbrace = ctx->LBRACE() )
26✔
256
  {
257
    addToken( "{", lbrace, linebuilder.openingBracketStyle( false, true ) );
26✔
258
    ++_currentgroup;
26✔
259
    _currentscope |= FmtToken::Scope::DICT;
26✔
260
    size_t curcount = linebuilder.currentTokens().size();
26✔
261
    visitIndexBindingList( ctx->indexBindingList() );
26✔
262
    _currentscope &= ~FmtToken::Scope::DICT;
26✔
263
    --_currentgroup;
26✔
264
    addToken( "}", ctx->RBRACE(),
26✔
265
              linebuilder.closingBracketStyle( curcount ) & ~FmtToken::BREAKPOINT );
26✔
266
  }
267

268
  return {};
59✔
269
}
270

271
antlrcpp::Any PrettifyFileProcessor::visitBindingDeclarationInitializer(
45✔
272
    EscriptGrammar::EscriptParser::BindingDeclarationInitializerContext* ctx )
273
{
274
  addToken( ":=", ctx->ASSIGN(), linebuilder.assignmentStyle() );
45✔
275
  visitExpression( ctx->expression() );
45✔
276

277
  return {};
45✔
278
}
279
antlrcpp::Any PrettifyFileProcessor::visitIndexBindingList(
26✔
280
    EscriptGrammar::EscriptParser::IndexBindingListContext* ctx )
281
{
282
  auto args = ctx->indexBinding();
26✔
283
  for ( size_t i = 0; i < args.size(); ++i )
88✔
284
  {
285
    visitIndexBinding( args[i] );
62✔
286

287
    if ( i < args.size() - 1 )
62✔
288
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() );
36✔
289
  }
290

291
  return {};
52✔
292
}
26✔
293

294
antlrcpp::Any PrettifyFileProcessor::visitSequenceBindingList(
33✔
295
    EscriptGrammar::EscriptParser::SequenceBindingListContext* ctx )
296
{
297
  auto args = ctx->sequenceBinding();
33✔
298
  for ( size_t i = 0; i < args.size(); ++i )
135✔
299
  {
300
    visitSequenceBinding( args[i] );
102✔
301
    if ( i < args.size() - 1 )
102✔
302
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() );
69✔
303
  }
304

305
  return {};
66✔
306
}
33✔
307

308
antlrcpp::Any PrettifyFileProcessor::visitIndexBinding(
62✔
309
    EscriptGrammar::EscriptParser::IndexBindingContext* ctx )
310
{
311
  if ( auto identifier = ctx->IDENTIFIER() )
62✔
312
  {
313
    make_identifier( identifier );
57✔
314
  }
315

316
  if ( auto ellipsis = ctx->ELLIPSIS() )
62✔
317
  {
318
    addToken( "...", ellipsis, linebuilder.ellipsisStyle() );
9✔
319
  }
320
  else if ( auto expression = ctx->expression() )
53✔
321
  {
322
    // This corresponds to an expression index, eg the [foo] in `var { [foo]: bar } := baz;`, so
323
    // force it to be unattached if we have bracket spacing.
324
    addToken( "[", ctx->LBRACK(), FmtToken::NONE );
5✔
325
    visitExpression( expression );
5✔
326
    addToken( "]", ctx->RBRACK(), FmtToken::ATTACHED );
5✔
327
  }
328

329
  if ( auto binding = ctx->binding() )
62✔
330
  {
331
    visitBinding( binding );
25✔
332
  }
333

334
  return {};
62✔
335
}
336

337
antlrcpp::Any PrettifyFileProcessor::visitBinding(
25✔
338
    EscriptGrammar::EscriptParser::BindingContext* ctx )
339
{
340
  // We always want it attached, eg. `foo:` (and not `foo :`) but we may not want a space after the
341
  // colon, eg.:
342
  //   `foo: bar` (FormatterAssignmentSpacing=1), vs
343
  //   `foo:bar` (FormatterAssignmentSpacing=0)
344
  addToken( ":", ctx->COLON(),
25✔
345
            FmtToken::ATTACHED |
346
                ( compilercfg.FormatterAssignmentSpacing ? FmtToken::SPACE : FmtToken::NONE ) );
25✔
347

348
  if ( auto identifier = ctx->IDENTIFIER() )
25✔
349
  {
350
    make_identifier( identifier );
16✔
351
  }
352
  else if ( auto binding_decl = ctx->bindingDeclaration() )
9✔
353
  {
354
    visitBindingDeclaration( binding_decl );
9✔
355
  }
356

357
  return {};
25✔
358
}
359

360
antlrcpp::Any PrettifyFileProcessor::visitSequenceBinding(
102✔
361
    EscriptGrammar::EscriptParser::SequenceBindingContext* ctx )
362
{
363
  if ( auto identifier = ctx->IDENTIFIER() )
102✔
364
  {
365
    make_identifier( identifier );
97✔
366
    if ( auto ellipsis = ctx->ELLIPSIS() )
97✔
367
    {
368
      addToken( "...", ellipsis, linebuilder.ellipsisStyle() );
23✔
369
    }
370
  }
371
  else if ( auto binding_decl = ctx->bindingDeclaration() )
5✔
372
  {
373
    visitBindingDeclaration( binding_decl );
5✔
374
  }
375

376
  return {};
102✔
377
}
378

379
antlrcpp::Any PrettifyFileProcessor::visitConstStatement(
65✔
380
    EscriptParser::ConstStatementContext* ctx )
381
{
382
  addToken( "const", ctx->TOK_CONST(), FmtToken::SPACE );
65✔
383
  auto const_declaration_ctx = ctx->constantDeclaration();
65✔
384
  make_identifier( const_declaration_ctx->IDENTIFIER() );
65✔
385

386
  if ( auto variable_declaration_initializer =
65✔
387
           const_declaration_ctx->variableDeclarationInitializer() )
65✔
388
  {
389
    if ( auto assign = variable_declaration_initializer->ASSIGN() )
65✔
390
      addToken( ":=", assign, linebuilder.assignmentStyle() );
65✔
391
    if ( auto expression = variable_declaration_initializer->expression() )
65✔
392
      visitExpression( expression );
65✔
393
    else if ( auto array = variable_declaration_initializer->ARRAY() )
×
394
      addToken( "array", array, FmtToken::SPACE );
×
395
  }
396
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
65✔
397

398
  linebuilder.buildLine( _currindent );
65✔
399
  return {};
65✔
400
}
401

402
antlrcpp::Any PrettifyFileProcessor::visitDictInitializerExpression(
47✔
403
    EscriptParser::DictInitializerExpressionContext* ctx )
404
{
405
  visitExpression( ctx->expression( 0 ) );  // key
47✔
406

407
  if ( ctx->ELLIPSIS() )
47✔
408
  {
409
    addToken( "...", ctx->ELLIPSIS(), linebuilder.ellipsisStyle() );
5✔
410
  }
411
  else
412
  {
413
    if ( ctx->expression().size() > 1 )
42✔
414
    {
415
      addToken( "->", ctx->ARROW(),
39✔
416
                linebuilder.delimiterStyle() & ~FmtToken::BREAKPOINT & ~FmtToken::ATTACHED );
39✔
417
      visitExpression( ctx->expression( 1 ) );
39✔
418
    }
419
  }
420
  return {};
47✔
421
}
422

423
antlrcpp::Any PrettifyFileProcessor::visitDoStatement( EscriptParser::DoStatementContext* ctx )
5✔
424
{
425
  make_statement_label( ctx->statementLabel() );
5✔
426
  addToken( "do", ctx->DO(), FmtToken::SPACE | FmtToken::BREAKPOINT );
5✔
427
  linebuilder.buildLine( _currindent );
5✔
428

429
  visitBlock( ctx->block() );
5✔
430

431
  addToken( "dowhile", ctx->DOWHILE(), FmtToken::SPACE );
5✔
432
  visitParExpression( ctx->parExpression() );
5✔
433
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
5✔
434
  linebuilder.buildLine( _currindent );
5✔
435
  return {};
5✔
436
}
437

438
antlrcpp::Any PrettifyFileProcessor::visitEnumListEntry( EscriptParser::EnumListEntryContext* ctx )
40✔
439
{
440
  make_identifier( ctx->IDENTIFIER() );
40✔
441

442
  if ( auto expression = ctx->expression() )
40✔
443
  {
444
    addToken( ":=", ctx->ASSIGN(), linebuilder.assignmentStyle() );
21✔
445
    visitExpression( expression );
21✔
446
  }
447
  return {};
40✔
448
}
449
antlrcpp::Any PrettifyFileProcessor::visitEnumList( EscriptParser::EnumListContext* ctx )
13✔
450

451
{
452
  auto enums = ctx->enumListEntry();
13✔
453
  for ( size_t i = 0; i < enums.size(); ++i )
53✔
454
  {
455
    visitEnumListEntry( enums[i] );
40✔
456
    if ( i < enums.size() - 1 )
40✔
457
      addToken( ",", ctx->COMMA( i ), FmtToken::SPACE | FmtToken::ATTACHED );
27✔
458

459
    linebuilder.buildLine( _currindent );
40✔
460
  }
461
  return {};
26✔
462
}
13✔
463

464
antlrcpp::Any PrettifyFileProcessor::visitEnumStatement( EscriptParser::EnumStatementContext* ctx )
13✔
465
{
466
  addToken( "enum", ctx->ENUM(), FmtToken::SPACE );
13✔
467
  if ( auto class_token = ctx->CLASS() )
13✔
468
  {
469
    addToken( "class", class_token, FmtToken::SPACE );
3✔
470
  }
471
  make_identifier( ctx->IDENTIFIER() );
13✔
472
  linebuilder.buildLine( _currindent );
13✔
473
  ++_currindent;
13✔
474
  auto enums = visitEnumList( ctx->enumList() );
13✔
475
  --_currindent;
13✔
476

477
  addToken( "endenum", ctx->ENDENUM(), FmtToken::SPACE );
13✔
478
  linebuilder.buildLine( _currindent );
13✔
479
  return {};
26✔
480
}
13✔
481

482
antlrcpp::Any PrettifyFileProcessor::visitExitStatement( EscriptParser::ExitStatementContext* ctx )
6✔
483
{
484
  addToken( "exit", ctx->EXIT(), FmtToken::SPACE );
6✔
485
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
6✔
486
  linebuilder.buildLine( _currindent );
6✔
487
  return {};
6✔
488
}
489

490
antlrcpp::Any PrettifyFileProcessor::visitArrayInitializer(
129✔
491
    EscriptParser::ArrayInitializerContext* ctx )
492
{
493
  if ( auto lbrace = ctx->LBRACE() )
129✔
494
    addToken( "{", lbrace, linebuilder.openingBracketStyle( true ) );
125✔
495
  else if ( auto lparen = ctx->LPAREN() )
4✔
496
    addToken( "(", lparen, linebuilder.openingParenthesisStyle() );
4✔
497
  ++_currentgroup;
129✔
498
  size_t curcount = linebuilder.currentTokens().size();
129✔
499
  bool args = false;
129✔
500
  if ( auto expr = ctx->expressionList() )
129✔
501
    args = std::any_cast<bool>( visitExpressionList( expr ) );
104✔
502
  --_currentgroup;
129✔
503

504
  if ( auto rbrace = ctx->RBRACE() )
129✔
505
    addToken( "}", rbrace, linebuilder.closingBracketStyle( curcount ) );
125✔
506
  else if ( auto rparen = ctx->RPAREN() )
4✔
507
    addToken( ")", rparen, linebuilder.closingParenthesisStyle( args ) );
4✔
508
  return {};
129✔
509
}
510

511
antlrcpp::Any PrettifyFileProcessor::visitExplicitArrayInitializer(
133✔
512
    EscriptParser::ExplicitArrayInitializerContext* ctx )
513
{
514
  ++_currentgroup;
133✔
515
  _currentscope |= FmtToken::Scope::ARRAY;
133✔
516
  addToken( "array", ctx->ARRAY(), FmtToken::SPACE );
133✔
517
  if ( auto init = ctx->arrayInitializer() )
133✔
518
    visitArrayInitializer( init );
129✔
519
  _currentscope &= ~FmtToken::Scope::ARRAY;
133✔
520
  --_currentgroup;
133✔
521
  return {};
133✔
522
}
523

524
antlrcpp::Any PrettifyFileProcessor::visitDictInitializerExpressionList(
23✔
525
    EscriptParser::DictInitializerExpressionListContext* ctx )
526
{
527
  auto inits = ctx->dictInitializerExpression();
23✔
528
  ++_currentgroup;
23✔
529
  for ( size_t i = 0; i < inits.size(); ++i )
70✔
530
  {
531
    visitDictInitializerExpression( inits[i] );
47✔
532
    if ( i < inits.size() - 1 )
47✔
533
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() );
24✔
534
  }
535
  --_currentgroup;
23✔
536
  return {};
46✔
537
}
23✔
538

539
antlrcpp::Any PrettifyFileProcessor::visitDictInitializer(
35✔
540
    EscriptParser::DictInitializerContext* ctx )
541
{
542
  addToken( "{", ctx->LBRACE(), linebuilder.openingBracketStyle( true ) );
35✔
543
  size_t curcount = linebuilder.currentTokens().size();
35✔
544
  if ( auto expr = ctx->dictInitializerExpressionList() )
35✔
545
    visitDictInitializerExpressionList( expr );
23✔
546

547
  addToken( "}", ctx->RBRACE(), linebuilder.closingBracketStyle( curcount ) );
35✔
548
  return {};
35✔
549
}
550

551
antlrcpp::Any PrettifyFileProcessor::visitExplicitDictInitializer(
50✔
552
    EscriptParser::ExplicitDictInitializerContext* ctx )
553
{
554
  ++_currentgroup;
50✔
555
  _currentscope |= FmtToken::Scope::DICT;
50✔
556
  addToken( "dictionary", ctx->DICTIONARY(), FmtToken::SPACE );
50✔
557
  if ( auto init = ctx->dictInitializer() )
50✔
558
    visitDictInitializer( init );
35✔
559
  _currentscope &= ~FmtToken::Scope::DICT;
50✔
560
  --_currentgroup;
50✔
561
  return {};
50✔
562
}
563

564
antlrcpp::Any PrettifyFileProcessor::visitStructInitializerExpressionList(
79✔
565
    EscriptParser::StructInitializerExpressionListContext* ctx )
566
{
567
  auto inits = ctx->structInitializerExpression();
79✔
568
  for ( size_t i = 0; i < inits.size(); ++i )
245✔
569
  {
570
    visitStructInitializerExpression( inits[i] );
166✔
571
    if ( i < inits.size() - 1 )
166✔
572
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() );
87✔
573
  }
574
  return {};
158✔
575
}
79✔
576

577
antlrcpp::Any PrettifyFileProcessor::visitStructInitializer(
98✔
578
    EscriptParser::StructInitializerContext* ctx )
579
{
580
  addToken( "{", ctx->LBRACE(), linebuilder.openingBracketStyle( true ) );
98✔
581
  ++_currentgroup;
98✔
582
  size_t curcount = linebuilder.currentTokens().size();
98✔
583
  if ( auto expr = ctx->structInitializerExpressionList() )
98✔
584
    visitStructInitializerExpressionList( expr );
79✔
585
  --_currentgroup;
98✔
586

587
  addToken( "}", ctx->RBRACE(), linebuilder.closingBracketStyle( curcount ) );
98✔
588
  return {};
98✔
589
}
590

591
antlrcpp::Any PrettifyFileProcessor::visitExplicitErrorInitializer(
15✔
592
    EscriptParser::ExplicitErrorInitializerContext* ctx )
593
{
594
  addToken( "error", ctx->TOK_ERROR(), FmtToken::SPACE );
15✔
595
  if ( auto init = ctx->structInitializer() )
15✔
596
    visitStructInitializer( init );
12✔
597
  return {};
15✔
598
}
599

600
antlrcpp::Any PrettifyFileProcessor::visitBareArrayInitializer(
191✔
601
    EscriptParser::BareArrayInitializerContext* ctx )
602
{
603
  _currentscope |= FmtToken::Scope::ARRAY;
191✔
604
  addToken( "{", ctx->LBRACE(), linebuilder.openingBracketStyle() & ~FmtToken::ATTACHED );
191✔
605
  ++_currentgroup;
191✔
606
  size_t curcount = linebuilder.currentTokens().size();
191✔
607
  if ( auto expr = ctx->expressionList() )
191✔
608
    visitExpressionList( expr );
161✔
609
  --_currentgroup;
191✔
610
  addToken( "}", ctx->RBRACE(), linebuilder.closingBracketStyle( curcount ) );
191✔
611
  _currentscope &= ~FmtToken::Scope::ARRAY;
191✔
612
  return {};
191✔
613
}
614

615
antlrcpp::Any PrettifyFileProcessor::visitExplicitStructInitializer(
100✔
616
    EscriptParser::ExplicitStructInitializerContext* ctx )
617
{
618
  ++_currentgroup;
100✔
619
  _currentscope |= FmtToken::Scope::STRUCT;
100✔
620
  addToken( "struct", ctx->STRUCT(), FmtToken::SPACE );
100✔
621
  if ( auto init = ctx->structInitializer() )
100✔
622
    visitStructInitializer( init );
86✔
623
  _currentscope &= ~FmtToken::Scope::STRUCT;
100✔
624
  --_currentgroup;
100✔
625
  return {};
100✔
626
}
627

628
antlrcpp::Any PrettifyFileProcessor::visitExpressionList(
4,415✔
629
    EscriptParser::ExpressionListContext* ctx )
630
{
631
  auto args = ctx->expressionListEntry();
4,415✔
632
  for ( size_t i = 0; i < args.size(); ++i )
10,167✔
633
  {
634
    visitExpression( args[i]->expression() );
5,752✔
635

636
    if ( args[i]->ELLIPSIS() )
5,752✔
637
      addToken( "...", args[i]->ELLIPSIS(), linebuilder.ellipsisStyle() );
201✔
638

639
    if ( i < args.size() - 1 )
5,752✔
640
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() | FmtToken::PREFERRED_BREAK );
1,337✔
641
  }
642
  return !args.empty();
8,830✔
643
}
4,415✔
644

645
antlrcpp::Any PrettifyFileProcessor::visitIndexList( EscriptParser::IndexListContext* ctx )
369✔
646
{
647
  auto args = ctx->expression();
369✔
648
  for ( size_t i = 0; i < args.size(); ++i )
771✔
649
  {
650
    visitExpression( args[i] );
402✔
651
    if ( i < args.size() - 1 )
402✔
652
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() | FmtToken::PREFERRED_BREAK );
33✔
653
  }
654
  return {};
738✔
655
}
369✔
656

657
antlrcpp::Any PrettifyFileProcessor::visitExpression( EscriptParser::ExpressionContext* ctx )
19,102✔
658
{
659
  if ( auto prim = ctx->primary() )
19,102✔
660
  {
661
    visitPrimary( prim );
15,277✔
662
    return true;
15,277✔
663
  }
664
  if ( ctx->prefix )
3,825✔
665
  {
666
    addToken( ctx->prefix->getText(), ctx->prefix,
159✔
667
              ctx->prefix->getType() == EscriptLexer::BANG_B ? FmtToken::SPACE : FmtToken::NONE );
159✔
668
    visitExpression( ctx->expression( 0 ) );
159✔
669
    return true;
159✔
670
  }
671
  if ( ctx->postfix )
3,666✔
672
  {
673
    visitExpression( ctx->expression( 0 ) );
50✔
674
    addToken( ctx->postfix->getText(), ctx->postfix, FmtToken::SPACE | FmtToken::ATTACHED );
50✔
675
    return true;
50✔
676
  }
677
  if ( ctx->bop && ctx->expression().size() == 2 )
3,616✔
678
  {
679
    visitExpression( ctx->expression( 0 ) );  // left
2,292✔
680
    int style = FmtToken::NONE;
2,292✔
681
    switch ( ctx->bop->getType() )
2,292✔
682
    {
683
    case EscriptLexer::OR_A:
94✔
684
    case EscriptLexer::OR_B:
685
    case EscriptLexer::AND_A:
686
    case EscriptLexer::AND_B:
687
      style = FmtToken::SPACE | FmtToken::BREAKPOINT | FmtToken::PREFERRED_BREAK_LOGICAL;
94✔
688
      break;
94✔
689
    case EscriptLexer::ADDMEMBER:
59✔
690
    case EscriptLexer::DELMEMBER:
691
    case EscriptLexer::CHKMEMBER:
692
      style = FmtToken::ATTACHED;
59✔
693
      break;
59✔
694
    case EscriptLexer::ASSIGN:
721✔
695
    case EscriptLexer::ADD_ASSIGN:
696
    case EscriptLexer::SUB_ASSIGN:
697
    case EscriptLexer::MUL_ASSIGN:
698
    case EscriptLexer::DIV_ASSIGN:
699
    case EscriptLexer::MOD_ASSIGN:
700
      _currentscope |= FmtToken::Scope::VAR;  // matches with visitStatement
721✔
701
      style = linebuilder.assignmentStyle();
721✔
702
      break;
721✔
703
    case EscriptLexer::TOK_IN:
7✔
704
      style = FmtToken::SPACE;
7✔
705
      break;
7✔
706
    case EscriptLexer::LE:
458✔
707
    case EscriptLexer::GE:
708
    case EscriptLexer::GT:
709
    case EscriptLexer::LT:
710
    case EscriptLexer::EQUAL:
711
    case EscriptLexer::NOTEQUAL_A:
712
    case EscriptLexer::NOTEQUAL_B:
713
      style = linebuilder.comparisonStyle();
458✔
714
      break;
458✔
715
    case EscriptLexer::ADD:
881✔
716
    case EscriptLexer::SUB:
717
    case EscriptLexer::MUL:
718
    case EscriptLexer::DIV:
719
    case EscriptLexer::MOD:
720
    case EscriptLexer::LSHIFT:
721
    case EscriptLexer::RSHIFT:
722
    case EscriptLexer::BITAND:
723
    case EscriptLexer::BITOR:
724
      style = linebuilder.operatorStyle();
881✔
725
      break;
881✔
726
    case EscriptLexer::ELVIS:
48✔
727
    {
728
      // TODO before it sets breakpoint before
729
      // if really needed should be a flag like attached
730
      style = FmtToken::SPACE | FmtToken::BREAKPOINT;
48✔
731
      break;
48✔
732
    }
733
    default:
24✔
734
      style = FmtToken::SPACE;
24✔
735
    }
736
    addToken( ctx->bop->getText(), ctx->bop, style );
2,292✔
737

738
    visitExpression( ctx->expression( 1 ) );  // right
2,292✔
739
    return true;
2,292✔
740
  }
741
  if ( auto suffix = ctx->expressionSuffix() )
1,324✔
742
  {
743
    expression_suffix( ctx->expression( 0 ), suffix );
1,292✔
744
    return true;
1,292✔
745
  }
746
  if ( ctx->QUESTION() )
32✔
747
  {
748
    visitExpression( ctx->expression( 0 ) );  // conditional
32✔
749
    addToken( "?", ctx->QUESTION(), FmtToken::SPACE | FmtToken::BREAKPOINT );
32✔
750
    visitExpression( ctx->expression( 1 ) );  // consequent
32✔
751
    addToken( ":", ctx->COLON(), FmtToken::SPACE | FmtToken::BREAKPOINT );
32✔
752

753
    visitExpression( ctx->expression( 2 ) );  // alternate
32✔
754
    return true;
32✔
755
  }
756

757
  return false;
×
758
}
759

760
antlrcpp::Any PrettifyFileProcessor::expression_suffix(
1,292✔
761
    EscriptParser::ExpressionContext* expr_ctx,
762
    EscriptParser::ExpressionSuffixContext* expr_suffix_ctx )
763
{
764
  if ( auto indexing = expr_suffix_ctx->indexingSuffix() )
1,292✔
765
  {
766
    visitExpression( expr_ctx );
369✔
767
    addToken( "[", indexing->LBRACK(), FmtToken::ATTACHED );
369✔
768
    visitIndexList( indexing->indexList() );
369✔
769
    addToken( "]", indexing->RBRACK(), FmtToken::SPACE | FmtToken::ATTACHED );
369✔
770
  }
771
  else if ( auto member = expr_suffix_ctx->navigationSuffix() )
923✔
772
  {
773
    visitExpression( expr_ctx );
308✔
774
    addToken( ".", member->DOT(), FmtToken::ATTACHED );
308✔
775
    if ( auto string_literal = member->STRING_LITERAL() )
308✔
776
      make_string_literal( string_literal );
1✔
777
    else if ( auto identifier = member->IDENTIFIER() )
307✔
778
      make_identifier( identifier );
299✔
779
    else if ( auto function_keyword = member->FUNCTION() )
8✔
780
      make_identifier( function_keyword );
8✔
781
  }
782
  else if ( auto method = expr_suffix_ctx->methodCallSuffix() )
615✔
783
  {
784
    visitExpression( expr_ctx );
529✔
785
    addToken( ".", method->DOT(), FmtToken::ATTACHED );
529✔
786
    make_identifier( method->IDENTIFIER() );
529✔
787
    addToken( "(", method->LPAREN(), linebuilder.openingParenthesisStyle() );
529✔
788
    bool args = false;
529✔
789
    if ( auto expr = method->expressionList() )
529✔
790
      args = std::any_cast<bool>( visitExpressionList( expr ) );
400✔
791
    addToken( ")", method->RPAREN(), linebuilder.closingParenthesisStyle( args ) );
529✔
792
  }
793
  else if ( auto function_call = expr_suffix_ctx->functionCallSuffix() )
86✔
794
  {
795
    visitExpression( expr_ctx );
86✔
796
    addToken( "(", function_call->LPAREN(), linebuilder.openingParenthesisStyle() );
86✔
797
    bool args = false;
86✔
798
    if ( auto expr = function_call->expressionList() )
86✔
799
      args = std::any_cast<bool>( visitExpressionList( expr ) );
76✔
800
    addToken( ")", function_call->RPAREN(), linebuilder.closingParenthesisStyle( args ) );
86✔
801
  }
802
  return {};
1,292✔
803
}
804

805
antlrcpp::Any PrettifyFileProcessor::visitFloatLiteral( EscriptParser::FloatLiteralContext* ctx )
224✔
806
{
807
  if ( auto float_literal = ctx->FLOAT_LITERAL() )
224✔
808
    return make_float_literal( float_literal );
221✔
809
  if ( auto hex_float_literal = ctx->HEX_FLOAT_LITERAL() )
3✔
810
    return make_float_literal( hex_float_literal );
3✔
811

812
  return visitChildren( ctx );
×
813
}
814

815
antlrcpp::Any PrettifyFileProcessor::visitForeachIterableExpression(
86✔
816
    EscriptParser::ForeachIterableExpressionContext* ctx )
817
{
818
  if ( auto parExpression = ctx->parExpression() )
86✔
819
  {
820
    visitParExpression( parExpression );
23✔
821
  }
822
  else if ( auto functionCall = ctx->functionCall() )
63✔
823
  {
824
    visitFunctionCall( functionCall );
15✔
825
  }
826
  else if ( auto scopedIdentifier = ctx->scopedIdentifier() )
48✔
827
  {
828
    visitScopedIdentifier( scopedIdentifier );
1✔
829
  }
830
  else if ( auto scopedFunctionCall = ctx->scopedFunctionCall() )
47✔
831
  {
832
    visitScopedFunctionCall( scopedFunctionCall );
1✔
833
  }
834
  else if ( auto identifier = ctx->IDENTIFIER() )
46✔
835
  {
836
    make_identifier( identifier );
38✔
837
  }
838
  else if ( auto explicitArrayInitializer = ctx->explicitArrayInitializer() )
8✔
839
  {
840
    visitExplicitArrayInitializer( explicitArrayInitializer );
3✔
841
  }
842
  else if ( auto bareArrayInitializer = ctx->bareArrayInitializer() )
5✔
843
  {
844
    visitBareArrayInitializer( bareArrayInitializer );
5✔
845
  }
846
  return {};
86✔
847
}
848

849
antlrcpp::Any PrettifyFileProcessor::visitForeachStatement(
86✔
850
    EscriptParser::ForeachStatementContext* ctx )
851
{
852
  make_statement_label( ctx->statementLabel() );
86✔
853
  addToken( "foreach", ctx->FOREACH(), FmtToken::SPACE );
86✔
854
  make_identifier( ctx->IDENTIFIER() );
86✔
855
  addToken( "in", ctx->TOK_IN(), FmtToken::SPACE );
86✔
856
  visitForeachIterableExpression( ctx->foreachIterableExpression() );
86✔
857
  linebuilder.buildLine( _currindent );
86✔
858

859
  visitBlock( ctx->block() );
86✔
860

861
  addToken( "endforeach", ctx->ENDFOREACH(), FmtToken::SPACE );
86✔
862
  linebuilder.buildLine( _currindent );
86✔
863
  return {};
86✔
864
}
865

866
antlrcpp::Any PrettifyFileProcessor::visitForStatement( EscriptParser::ForStatementContext* ctx )
35✔
867
{
868
  make_statement_label( ctx->statementLabel() );
35✔
869

870
  auto forGroup = ctx->forGroup();
35✔
871

872
  addToken( "for", ctx->FOR(), FmtToken::SPACE );
35✔
873
  if ( auto basicForStatement = forGroup->basicForStatement() )
35✔
874
    visitBasicForStatement( basicForStatement );
14✔
875
  else if ( auto cstyleForStatement = forGroup->cstyleForStatement() )
21✔
876
    visitCstyleForStatement( cstyleForStatement );
21✔
877
  addToken( "endfor", ctx->ENDFOR(), FmtToken::SPACE );
35✔
878
  linebuilder.buildLine( _currindent );
35✔
879
  return {};
35✔
880
}
881

882
antlrcpp::Any PrettifyFileProcessor::visitFunctionCall( EscriptParser::FunctionCallContext* ctx )
3,842✔
883
{
884
  make_identifier( ctx->IDENTIFIER() );
3,842✔
885
  _currentscope |= FmtToken::Scope::FUNCTION;
3,842✔
886

887
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle(),
3,842✔
888
            FmtContext::PREFERRED_BREAK_START );
889

890
  bool argcount = false;
3,842✔
891
  if ( auto args = ctx->expressionList() )
3,842✔
892
    argcount = std::any_cast<bool>( visitExpressionList( args ) );
3,674✔
893

894
  addToken( ")", ctx->RPAREN(), linebuilder.closingParenthesisStyle( argcount ),
3,842✔
895
            FmtContext::PREFERRED_BREAK_END );
896
  _currentscope &= ~FmtToken::Scope::FUNCTION;
3,842✔
897
  return {};
3,842✔
898
}
899
antlrcpp::Any PrettifyFileProcessor::visitFunctionDeclaration(
420✔
900
    EscriptParser::FunctionDeclarationContext* ctx )
901
{
902
  if ( auto exported = ctx->EXPORTED() )
420✔
903
    addToken( "exported", exported, FmtToken::SPACE );
3✔
904
  addToken( "function", ctx->FUNCTION(), FmtToken::SPACE );
420✔
905
  make_identifier( ctx->IDENTIFIER() );
420✔
906
  visitFunctionParameters( ctx->functionParameters() );
420✔
907

908
  visitBlock( ctx->block() );
420✔
909

910
  addToken( "endfunction", ctx->ENDFUNCTION(), FmtToken::SPACE );
420✔
911
  linebuilder.buildLine( _currindent );
420✔
912
  return {};
420✔
913
}
914

915
antlrcpp::Any PrettifyFileProcessor::visitFunctionParameters(
518✔
916
    EscriptParser::FunctionParametersContext* ctx )
917
{
918
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle(),
518✔
919
            FmtContext::PREFERRED_BREAK_START );
920

921
  bool argcount = false;
518✔
922
  if ( auto args = ctx->functionParameterList() )
518✔
923
    argcount = std::any_cast<bool>( visitFunctionParameterList( args ) );
431✔
924

925
  auto closingstyle = linebuilder.closingParenthesisStyle( argcount );
518✔
926
  if ( _suppressnewline )  // add space if newline is suppressed
518✔
927
    closingstyle |= FmtToken::SPACE;
98✔
928
  addToken( ")", ctx->RPAREN(), closingstyle, FmtContext::PREFERRED_BREAK_END );
518✔
929
  if ( !_suppressnewline )
518✔
930
    linebuilder.buildLine( _currindent );
420✔
931
  return {};
518✔
932
}
933

934
antlrcpp::Any PrettifyFileProcessor::visitFunctionParameterList(
431✔
935
    EscriptParser::FunctionParameterListContext* ctx )
936
{
937
  auto params = ctx->functionParameter();
431✔
938
  for ( size_t i = 0; i < params.size(); ++i )
1,163✔
939
  {
940
    visitFunctionParameter( params[i] );
732✔
941
    if ( i < params.size() - 1 )
732✔
942
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() | FmtToken::PREFERRED_BREAK );
301✔
943
  }
944
  return !params.empty();
862✔
945
}
431✔
946

947
antlrcpp::Any PrettifyFileProcessor::visitFunctionParameter(
732✔
948
    EscriptParser::FunctionParameterContext* ctx )
949
{
950
  if ( auto byref = ctx->BYREF() )
732✔
951
    addToken( "byref", byref, FmtToken::SPACE );
28✔
952
  if ( auto unused = ctx->UNUSED() )
732✔
953
    addToken( "unused", unused, FmtToken::SPACE );
21✔
954
  if ( auto default_keyword = ctx->DEFAULT() )
732✔
955
    addToken( "default", default_keyword, FmtToken::SPACE );
3✔
956
  make_identifier( ctx->IDENTIFIER() );
732✔
957

958
  if ( ctx->ELLIPSIS() )
732✔
959
    addToken( "...", ctx->ELLIPSIS(), linebuilder.ellipsisStyle() );
42✔
960

961
  if ( auto expression = ctx->expression() )
732✔
962
  {
963
    addToken( ":=", ctx->ASSIGN(), linebuilder.assignmentStyle() );
40✔
964
    visitExpression( expression );
40✔
965
  }
966
  return {};
732✔
967
}
968

969
antlrcpp::Any PrettifyFileProcessor::visitBreakStatement(
44✔
970
    EscriptParser::BreakStatementContext* ctx )
971
{
972
  addToken( "break", ctx->BREAK(), FmtToken::SPACE );
44✔
973
  if ( auto identifier = ctx->IDENTIFIER() )
44✔
974
    make_identifier( identifier );
4✔
975
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
44✔
976
  linebuilder.buildLine( _currindent );
44✔
977
  return {};
44✔
978
}
979

980
antlrcpp::Any PrettifyFileProcessor::visitSwitchBlockStatementGroup(
92✔
981
    EscriptParser::SwitchBlockStatementGroupContext* ctx )
982
{
983
  if ( ctx->switchLabel().size() == 1 )
92✔
984
    if ( compilercfg.FormatterAllowShortCaseLabelsOnASingleLine )
91✔
985
      linebuilder.markPackableLineStart();
91✔
986
  for ( const auto& switchLabel : ctx->switchLabel() )
185✔
987
  {
988
    visitSwitchLabel( switchLabel );
93✔
989
    linebuilder.buildLine( _currindent );
93✔
990
  }
92✔
991
  visitBlock( ctx->block() );
92✔
992
  if ( compilercfg.FormatterAllowShortCaseLabelsOnASingleLine )
92✔
993
    linebuilder.markPackableLineEnd();
92✔
994
  if ( ctx->switchLabel().size() == 1 )
92✔
995
    linebuilder.buildLine( _currindent );
91✔
996
  return {};
92✔
997
}
998

999
antlrcpp::Any PrettifyFileProcessor::visitUninitFunctionDeclaration(
15✔
1000
    EscriptParser::UninitFunctionDeclarationContext* ctx )
1001
{
1002
  addToken( "uninit", ctx->UNINIT(), FmtToken::SPACE );
15✔
1003
  addToken( "function", ctx->FUNCTION(), FmtToken::SPACE );
15✔
1004
  make_identifier( ctx->IDENTIFIER() );
15✔
1005
  _suppressnewline = true;
15✔
1006
  visitFunctionParameters( ctx->functionParameters() );
15✔
1007
  _suppressnewline = false;
15✔
1008
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
15✔
1009
  linebuilder.buildLine( _currindent );
15✔
1010
  return {};
15✔
1011
}
1012

1013
antlrcpp::Any PrettifyFileProcessor::visitSwitchLabel( EscriptParser::SwitchLabelContext* ctx )
93✔
1014
{
1015
  if ( auto integerLiteral = ctx->integerLiteral() )
93✔
1016
    visitIntegerLiteral( integerLiteral );
30✔
1017
  else if ( auto boolLiteral = ctx->boolLiteral() )
63✔
1018
    visitBoolLiteral( boolLiteral );
4✔
1019
  else if ( auto uninit = ctx->UNINIT() )
59✔
1020
    addToken( "uninit", uninit, FmtToken::SPACE );
1✔
1021
  else if ( auto identifier = ctx->IDENTIFIER() )
58✔
1022
    make_identifier( identifier );
18✔
1023
  else if ( auto string_literal = ctx->STRING_LITERAL() )
40✔
1024
    make_string_literal( string_literal );
21✔
1025
  else if ( auto defaultctx = ctx->DEFAULT() )
19✔
1026
    addToken( "default", defaultctx, FmtToken::SPACE );
16✔
1027
  else if ( auto scoped_ident = ctx->scopedIdentifier() )
3✔
1028
    visitScopedIdentifier( scoped_ident );
3✔
1029

1030
  addToken( ":", ctx->COLON(), FmtToken::SPACE | FmtToken::ATTACHED | FmtToken::BREAKPOINT );
93✔
1031
  linebuilder.markLastTokensAsSwitchLabel();
93✔
1032
  return {};
93✔
1033
}
1034

1035
antlrcpp::Any PrettifyFileProcessor::visitCaseStatement( EscriptParser::CaseStatementContext* ctx )
28✔
1036
{
1037
  make_statement_label( ctx->statementLabel() );
28✔
1038
  addToken( "case", ctx->CASE(), FmtToken::SPACE | FmtToken::BREAKPOINT );
28✔
1039
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle() & ~FmtToken::ATTACHED );
28✔
1040
  auto args = std::any_cast<bool>( visitExpression( ctx->expression() ) );
28✔
1041
  addToken( ")", ctx->RPAREN(), linebuilder.closingParenthesisStyle( args ) );
28✔
1042
  linebuilder.buildLine( _currindent );
28✔
1043
  ++_currindent;
28✔
1044
  size_t start = linebuilder.formattedLines().size();
28✔
1045
  for ( const auto& switchBlockStatementGroup : ctx->switchBlockStatementGroup() )
120✔
1046
  {
1047
    visitSwitchBlockStatementGroup( switchBlockStatementGroup );
92✔
1048
  }
28✔
1049
  --_currindent;
28✔
1050
  linebuilder.alignSingleLineSwitchStatements( start );
28✔
1051
  addToken( "endcase", ctx->ENDCASE(), FmtToken::SPACE | FmtToken::BREAKPOINT );
28✔
1052
  linebuilder.buildLine( _currindent );
28✔
1053
  return {};
28✔
1054
}
1055

1056
antlrcpp::Any PrettifyFileProcessor::visitClassBody(
167✔
1057
    EscriptGrammar::EscriptParser::ClassBodyContext* ctx )
1058
{
1059
  ++_currindent;
167✔
1060
  visitChildren( ctx );
167✔
1061
  --_currindent;
167✔
1062
  return {};
167✔
1063
}
1064

1065
antlrcpp::Any PrettifyFileProcessor::visitClassDeclaration(
167✔
1066
    EscriptGrammar::EscriptParser::ClassDeclarationContext* ctx )
1067
{
1068
  addToken( "class", ctx->CLASS(), FmtToken::SPACE );
167✔
1069
  make_identifier( ctx->IDENTIFIER() );
167✔
1070
  visitClassParameters( ctx->classParameters() );
167✔
1071

1072
  visitClassBody( ctx->classBody() );
167✔
1073

1074
  addToken( "endclass", ctx->ENDCLASS(), FmtToken::SPACE );
167✔
1075
  linebuilder.buildLine( _currindent );
167✔
1076
  return {};
167✔
1077
}
1078

1079
antlrcpp::Any PrettifyFileProcessor::visitClassParameters(
167✔
1080
    EscriptGrammar::EscriptParser::ClassParametersContext* ctx )
1081
{
1082
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle(),
167✔
1083
            FmtContext::PREFERRED_BREAK_START );
1084

1085
  bool argcount = false;
167✔
1086
  if ( auto args = ctx->classParameterList() )
167✔
1087
    argcount = std::any_cast<bool>( visitClassParameterList( args ) );
73✔
1088

1089
  auto closingstyle = linebuilder.closingParenthesisStyle( argcount );
167✔
1090
  if ( _suppressnewline )  // add space if newline is suppressed
167✔
1091
    closingstyle |= FmtToken::SPACE;
×
1092
  addToken( ")", ctx->RPAREN(), closingstyle, FmtContext::PREFERRED_BREAK_END );
167✔
1093
  if ( !_suppressnewline )
167✔
1094
    linebuilder.buildLine( _currindent );
167✔
1095
  return {};
167✔
1096
}
1097

1098
antlrcpp::Any PrettifyFileProcessor::visitClassParameterList(
73✔
1099
    EscriptGrammar::EscriptParser::ClassParameterListContext* ctx )
1100
{
1101
  auto params = ctx->IDENTIFIER();
73✔
1102
  for ( size_t i = 0; i < params.size(); ++i )
182✔
1103
  {
1104
    make_identifier( params[i] );
109✔
1105
    if ( i < params.size() - 1 )
109✔
1106
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() | FmtToken::PREFERRED_BREAK );
36✔
1107
  }
1108

1109
  return !params.empty();
146✔
1110
}
73✔
1111

1112
antlrcpp::Any PrettifyFileProcessor::visitContinueStatement(
28✔
1113
    EscriptParser::ContinueStatementContext* ctx )
1114
{
1115
  addToken( "continue", ctx->CONTINUE(), FmtToken::SPACE );
28✔
1116

1117
  if ( auto identifier = ctx->IDENTIFIER() )
28✔
1118
    make_identifier( identifier );
5✔
1119

1120
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
28✔
1121
  linebuilder.buildLine( _currindent );
28✔
1122
  return {};
28✔
1123
}
1124

1125
antlrcpp::Any PrettifyFileProcessor::visitBasicForStatement(
14✔
1126
    EscriptParser::BasicForStatementContext* ctx )
1127
{
1128
  make_identifier( ctx->IDENTIFIER() );
14✔
1129
  addToken( ":=", ctx->ASSIGN(), linebuilder.assignmentStyle() );
14✔
1130
  visitExpression( ctx->expression( 0 ) );
14✔
1131
  addToken( "to", ctx->TO(), FmtToken::SPACE );
14✔
1132
  visitExpression( ctx->expression( 1 ) );
14✔
1133
  linebuilder.buildLine( _currindent );
14✔
1134

1135
  visitBlock( ctx->block() );
14✔
1136
  return {};
14✔
1137
}
1138

1139
antlrcpp::Any PrettifyFileProcessor::visitCstyleForStatement(
21✔
1140
    EscriptParser::CstyleForStatementContext* ctx )
1141
{
1142
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle() & ~FmtToken::ATTACHED );
21✔
1143
  visitExpression( ctx->expression( 0 ) );
21✔
1144
  addToken( ";", ctx->SEMI( 0 ), linebuilder.delimiterStyle() );
21✔
1145
  visitExpression( ctx->expression( 1 ) );
21✔
1146
  addToken( ";", ctx->SEMI( 1 ), linebuilder.delimiterStyle() );
21✔
1147
  visitExpression( ctx->expression( 2 ) );
21✔
1148
  addToken( ")", ctx->RPAREN(), linebuilder.closingParenthesisStyle( true ) );
21✔
1149
  linebuilder.buildLine( _currindent );
21✔
1150

1151
  visitBlock( ctx->block() );
21✔
1152
  return {};
21✔
1153
}
1154

1155
antlrcpp::Any PrettifyFileProcessor::visitRepeatStatement(
15✔
1156
    EscriptParser::RepeatStatementContext* ctx )
1157
{
1158
  make_statement_label( ctx->statementLabel() );
15✔
1159
  addToken( "repeat", ctx->REPEAT(), FmtToken::SPACE );
15✔
1160
  linebuilder.buildLine( _currindent );
15✔
1161

1162
  visitBlock( ctx->block() );
15✔
1163

1164
  addToken( "until", ctx->UNTIL(), FmtToken::SPACE );
15✔
1165
  visitExpression( ctx->expression() );
15✔
1166
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
15✔
1167
  linebuilder.buildLine( _currindent );
15✔
1168
  return {};
15✔
1169
}
1170

1171
antlrcpp::Any PrettifyFileProcessor::visitReturnStatement(
208✔
1172
    EscriptParser::ReturnStatementContext* ctx )
1173
{
1174
  addToken( "return", ctx->RETURN(), FmtToken::SPACE );
208✔
1175
  if ( auto expression = ctx->expression() )
208✔
1176
    visitExpression( expression );
203✔
1177
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
208✔
1178
  linebuilder.buildLine( _currindent );
208✔
1179
  return {};
208✔
1180
}
1181

1182
antlrcpp::Any PrettifyFileProcessor::visitScopedFunctionCall(
58✔
1183
    EscriptParser::ScopedFunctionCallContext* ctx )
1184
{
1185
  if ( ctx->IDENTIFIER() )
58✔
1186
    make_identifier( ctx->IDENTIFIER() );  // scope
53✔
1187
  addToken( "::", ctx->COLONCOLON(), FmtToken::ATTACHED );
58✔
1188
  visitFunctionCall( ctx->functionCall() );
58✔
1189
  return {};
58✔
1190
}
1191

1192
antlrcpp::Any PrettifyFileProcessor::visitScopedIdentifier(
57✔
1193
    EscriptGrammar::EscriptParser::ScopedIdentifierContext* ctx )
1194
{
1195
  if ( ctx->scope )
57✔
1196
  {
1197
    addToken( ctx->scope->getText(), ctx->scope, FmtToken::NONE );
50✔
1198
    addToken( "::", ctx->COLONCOLON(), FmtToken::ATTACHED );
50✔
1199
  }
1200
  else
1201
  {
1202
    addToken( "::", ctx->COLONCOLON(), FmtToken::NONE );
7✔
1203
  }
1204
  addToken( ctx->identifier->getText(), ctx->identifier, FmtToken::SPACE );
57✔
1205
  return {};
57✔
1206
}
1207

1208
antlrcpp::Any PrettifyFileProcessor::visitFunctionReference(
231✔
1209
    EscriptParser::FunctionReferenceContext* ctx )
1210
{
1211
  addToken( "@", ctx->AT(), FmtToken::NONE );
231✔
1212

1213
  if ( ctx->scope )
231✔
1214
  {
1215
    addToken( ctx->scope->getText(), ctx->scope, FmtToken::NONE );
14✔
1216
    addToken( "::", ctx->COLONCOLON(), FmtToken::ATTACHED );
14✔
1217
  }
1218

1219
  addToken( ctx->function->getText(), ctx->function, FmtToken::SPACE );
231✔
1220
  return {};
231✔
1221
}
1222

1223
antlrcpp::Any PrettifyFileProcessor::visitFunctionExpression(
95✔
1224
    EscriptGrammar::EscriptParser::FunctionExpressionContext* ctx )
1225
{
1226
  addToken( "@", ctx->AT(), FmtToken::NONE );
95✔
1227

1228

1229
  _suppressnewline = true;  // functionparams force newline
95✔
1230
  if ( auto params = ctx->functionParameters() )
95✔
1231
    visitFunctionParameters( params );
83✔
1232
  _suppressnewline = false;
95✔
1233

1234
  // we want the starting { at the same line and not attached
1235
  addToken( "{", ctx->LBRACE(), linebuilder.openingBracketStyle() & ~FmtToken::ATTACHED );
95✔
1236
  if ( compilercfg.FormatterAllowShortFuncRefsOnASingleLine )
95✔
1237
    linebuilder.markPackableLineStart();
95✔
1238
  linebuilder.buildLine( _currindent );  // now start a newline
95✔
1239

1240
  ++_currentgroup;
95✔
1241
  size_t curcount = linebuilder.currentTokens().size();
95✔
1242
  visitBlock( ctx->block() );
95✔
1243
  --_currentgroup;
95✔
1244

1245
  addToken( "}", ctx->RBRACE(), linebuilder.closingBracketStyle( curcount ) );
95✔
1246
  if ( compilercfg.FormatterAllowShortFuncRefsOnASingleLine )
95✔
1247
    linebuilder.markPackableLineEnd();
95✔
1248
  return {};
95✔
1249
}
1250

1251
antlrcpp::Any PrettifyFileProcessor::visitGotoStatement( EscriptParser::GotoStatementContext* ctx )
×
1252
{
1253
  addToken( "goto", ctx->GOTO(), FmtToken::SPACE );
×
1254
  make_identifier( ctx->IDENTIFIER() );
×
1255
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
×
1256
  linebuilder.buildLine( _currindent );
×
1257
  return {};
×
1258
}
1259

1260
antlrcpp::Any PrettifyFileProcessor::visitIfStatement( EscriptParser::IfStatementContext* ctx )
261✔
1261
{
1262
  auto blocks = ctx->block();
261✔
1263
  auto par_expression = ctx->parExpression();
261✔
1264
  size_t num_expressions = par_expression.size();
261✔
1265
  for ( size_t clause_index = 0; clause_index < num_expressions; ++clause_index )
548✔
1266
  {
1267
    auto expression_ctx = par_expression.at( clause_index );
287✔
1268
    if ( !clause_index )
287✔
1269
      addToken( "if", ctx->IF(), FmtToken::SPACE );
261✔
1270
    else
1271
      addToken( "elseif", ctx->ELSEIF( clause_index - 1 ), FmtToken::SPACE );
26✔
1272
    auto expression_ast = visitParExpression( expression_ctx );
287✔
1273
    if ( !clause_index && ctx->THEN() )
287✔
1274
      addToken( "then", ctx->THEN(), FmtToken::SPACE );
1✔
1275

1276
    linebuilder.buildLine( _currindent );
287✔
1277

1278
    if ( blocks.size() > clause_index )
287✔
1279
      visitBlock( blocks.at( clause_index ) );
287✔
1280
  }
287✔
1281
  if ( ctx->ELSE() )
261✔
1282
  {
1283
    addToken( "else", ctx->ELSE(), FmtToken::SPACE );
90✔
1284
    linebuilder.buildLine( _currindent );
90✔
1285
    visitBlock( blocks.at( blocks.size() - 1 ) );
90✔
1286
  }
1287
  addToken( "endif", ctx->ENDIF(), FmtToken::SPACE );
261✔
1288
  linebuilder.buildLine( _currindent );
261✔
1289
  return {};
522✔
1290
}
261✔
1291

1292
antlrcpp::Any PrettifyFileProcessor::visitIncludeDeclaration(
55✔
1293
    EscriptParser::IncludeDeclarationContext* ctx )
1294
{
1295
  addToken( "include", ctx->INCLUDE(), FmtToken::SPACE );
55✔
1296
  visitStringIdentifier( ctx->stringIdentifier() );
55✔
1297
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
55✔
1298
  linebuilder.buildLine( _currindent );
55✔
1299
  return {};
55✔
1300
}
1301

1302
antlrcpp::Any PrettifyFileProcessor::visitInterpolatedString(
280✔
1303
    EscriptParser::InterpolatedStringContext* ctx )
1304
{
1305
  addToken( "$\"", ctx->INTERPOLATED_STRING_START(), FmtToken::SPACE );
280✔
1306
  visitChildren( ctx );
280✔
1307
  addToken( "\"", ctx->DOUBLE_QUOTE_INSIDE(), FmtToken::ATTACHED | FmtToken::SPACE );
280✔
1308
  return {};
280✔
1309
}
1310

1311
antlrcpp::Any PrettifyFileProcessor::visitInterpolatedStringPart(
906✔
1312
    EscriptParser::InterpolatedStringPartContext* ctx )
1313
{
1314
  if ( auto expression_ctx = ctx->expression() )
906✔
1315
  {
1316
    addToken( "{", ctx->LBRACE_INSIDE(), FmtToken::ATTACHED );
442✔
1317
    visitExpression( expression_ctx );
442✔
1318

1319
    if ( auto format_string = ctx->FORMAT_STRING() )
442✔
1320
    {
1321
      addToken( ":", ctx->COLON(), FmtToken::ATTACHED );
2✔
1322
      addToken( format_string->getText(), format_string, FmtToken::ATTACHED );
2✔
1323
    }
1324
    // TODO: this seems to be the only non token
1325
    Range r( *expression_ctx );
442✔
1326
    addToken( "}", r.end, FmtToken::ATTACHED, 0 );
442✔
1327
  }
1328

1329
  else if ( auto string_literal = ctx->STRING_LITERAL_INSIDE() )
464✔
1330
  {
1331
    addToken( string_literal->getText(), string_literal, FmtToken::ATTACHED );
435✔
1332
  }
1333
  else if ( auto lbrace = ctx->DOUBLE_LBRACE_INSIDE() )
29✔
1334
  {
1335
    addToken( "{{", lbrace, FmtToken::ATTACHED );
14✔
1336
  }
1337
  else if ( auto rbrace = ctx->DOUBLE_RBRACE() )
15✔
1338
  {
1339
    addToken( "}}", rbrace, FmtToken::ATTACHED );
12✔
1340
  }
1341
  else if ( auto escaped = ctx->REGULAR_CHAR_INSIDE() )
3✔
1342
  {
1343
    addToken( escaped->getText(), escaped, FmtToken::ATTACHED );
3✔
1344
  }
1345
  return {};
906✔
1346
}
1347

1348
antlrcpp::Any PrettifyFileProcessor::visitBoolLiteral( EscriptParser::BoolLiteralContext* ctx )
105✔
1349
{
1350
  if ( auto bool_false = ctx->BOOL_FALSE() )
105✔
1351
    make_bool_literal( bool_false );
40✔
1352
  else if ( auto bool_true = ctx->BOOL_TRUE() )
65✔
1353
    make_bool_literal( bool_true );
65✔
1354
  return {};
105✔
1355
}
1356

1357
antlrcpp::Any PrettifyFileProcessor::visitIntegerLiteral(
2,637✔
1358
    EscriptParser::IntegerLiteralContext* ctx )
1359
{
1360
  if ( auto decimal_literal = ctx->DECIMAL_LITERAL() )
2,637✔
1361
    return make_integer_literal( decimal_literal );
2,605✔
1362

1363
  if ( auto hex_literal = ctx->HEX_LITERAL() )
32✔
1364
    return make_integer_literal( hex_literal );
29✔
1365

1366
  if ( auto oct_literal = ctx->OCT_LITERAL() )
3✔
1367
    return make_integer_literal( oct_literal );
3✔
1368

NEW
1369
  if ( auto binary_literal = ctx->BINARY_LITERAL() )
×
1370
    return make_integer_literal( binary_literal );
×
1371

1372
  return visitChildren( ctx );
×
1373
}
1374

1375
antlrcpp::Any PrettifyFileProcessor::visitLiteral( EscriptParser::LiteralContext* ctx )
5,705✔
1376
{
1377
  if ( auto string_literal = ctx->STRING_LITERAL() )
5,705✔
1378
    return make_string_literal( string_literal );
2,688✔
1379
  if ( auto integer_literal = ctx->integerLiteral() )
3,017✔
1380
    return visitIntegerLiteral( integer_literal );
2,607✔
1381
  if ( auto float_literal = ctx->floatLiteral() )
410✔
1382
    return visitFloatLiteral( float_literal );
224✔
1383
  if ( auto uninit = ctx->UNINIT() )
186✔
1384
    addToken( "uninit", uninit, FmtToken::SPACE );
35✔
1385
  if ( auto bool_literal = ctx->boolLiteral() )
186✔
1386
    return visitBoolLiteral( bool_literal );
101✔
1387
  if ( auto regular_expression_literal = ctx->REGEXP_LITERAL() )
85✔
1388
    return make_regular_expression_literal( regular_expression_literal );
50✔
1389
  return visitChildren( ctx );
35✔
1390
}
1391

1392
antlrcpp::Any PrettifyFileProcessor::visitModuleFunctionDeclaration(
×
1393
    EscriptParser::ModuleFunctionDeclarationContext* ctx )
1394
{
1395
  make_identifier( ctx->IDENTIFIER() );
×
1396
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle() );
×
1397
  bool args = false;
×
1398
  if ( auto moduleFunctionParameterList = ctx->moduleFunctionParameterList() )
×
1399
    args = std::any_cast<bool>( visitModuleFunctionParameterList( moduleFunctionParameterList ) );
×
1400

1401
  addToken( ")", ctx->RPAREN(), linebuilder.closingParenthesisStyle( args ) );
×
1402
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
×
1403
  linebuilder.buildLine( _currindent );
×
1404
  return {};
×
1405
}
1406

1407
antlrcpp::Any PrettifyFileProcessor::visitModuleFunctionParameterList(
×
1408
    EscriptParser::ModuleFunctionParameterListContext* ctx )
1409
{
1410
  auto params = ctx->moduleFunctionParameter();
×
1411
  for ( size_t i = 0; i < params.size(); ++i )
×
1412
  {
1413
    visitModuleFunctionParameter( params[i] );
×
1414
    if ( i < params.size() - 1 )
×
1415
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() | FmtToken::PREFERRED_BREAK );
×
1416
  }
1417
  return !params.empty();
×
1418
}
×
1419

1420
antlrcpp::Any PrettifyFileProcessor::visitModuleFunctionParameter(
×
1421
    EscriptParser::ModuleFunctionParameterContext* ctx )
1422
{
1423
  make_identifier( ctx->IDENTIFIER() );
×
1424

1425
  if ( auto expression = ctx->expression() )
×
1426
  {
1427
    addToken( ":=", ctx->ASSIGN(), linebuilder.assignmentStyle() );
×
1428
    visitExpression( expression );
×
1429
  }
1430
  return {};
×
1431
}
1432

1433
antlrcpp::Any PrettifyFileProcessor::visitPrimary( EscriptParser::PrimaryContext* ctx )
15,277✔
1434
{
1435
  if ( auto literal = ctx->literal() )
15,277✔
1436
    return visitLiteral( literal );
5,705✔
1437
  if ( auto parExpression = ctx->parExpression() )
9,572✔
1438
    return visitParExpression( parExpression );
100✔
1439
  if ( auto functionCall = ctx->functionCall() )
9,472✔
1440
    return visitFunctionCall( functionCall );
3,769✔
1441
  if ( auto scopedIdentifier = ctx->scopedIdentifier() )
5,703✔
1442
    return visitScopedIdentifier( scopedIdentifier );
53✔
1443
  if ( auto scopedFunctionCall = ctx->scopedFunctionCall() )
5,650✔
1444
    return visitScopedFunctionCall( scopedFunctionCall );
57✔
1445
  if ( auto identifier = ctx->IDENTIFIER() )
5,593✔
1446
    return make_identifier( identifier );
4,506✔
1447
  if ( auto functionReference = ctx->functionReference() )
1,087✔
1448
    return visitFunctionReference( functionReference );
231✔
1449
  if ( auto functionExpression = ctx->functionExpression() )
856✔
1450
    return visitFunctionExpression( functionExpression );
95✔
1451
  if ( auto explicitArrayInitializer = ctx->explicitArrayInitializer() )
761✔
1452
    return visitExplicitArrayInitializer( explicitArrayInitializer );
130✔
1453
  if ( auto explicitStructInitializer = ctx->explicitStructInitializer() )
631✔
1454
    return visitExplicitStructInitializer( explicitStructInitializer );
100✔
1455
  if ( auto explicitDictInitializer = ctx->explicitDictInitializer() )
531✔
1456
    return visitExplicitDictInitializer( explicitDictInitializer );
50✔
1457
  if ( auto explicitErrorInitializer = ctx->explicitErrorInitializer() )
481✔
1458
    return visitExplicitErrorInitializer( explicitErrorInitializer );
15✔
1459
  if ( auto bareArrayInitializer = ctx->bareArrayInitializer() )
466✔
1460
    return visitBareArrayInitializer( bareArrayInitializer );
186✔
1461
  if ( auto interpolatedString = ctx->interpolatedString() )
280✔
1462
    return visitInterpolatedString( interpolatedString );
280✔
1463
  return {};
×
1464
}
1465

1466
antlrcpp::Any PrettifyFileProcessor::visitProgramDeclaration(
73✔
1467
    EscriptParser::ProgramDeclarationContext* ctx )
1468
{
1469
  addToken( "program", ctx->PROGRAM(), FmtToken::SPACE );
73✔
1470
  make_identifier( ctx->IDENTIFIER() );
73✔
1471
  visitProgramParameters( ctx->programParameters() );
73✔
1472
  linebuilder.buildLine( _currindent );
73✔
1473
  visitBlock( ctx->block() );
73✔
1474
  addToken( "endprogram", ctx->ENDPROGRAM(), FmtToken::SPACE );
73✔
1475
  linebuilder.buildLine( _currindent );
73✔
1476
  return {};
73✔
1477
}
1478

1479
antlrcpp::Any PrettifyFileProcessor::visitProgramParameterList(
12✔
1480
    EscriptParser::ProgramParameterListContext* ctx )
1481
{
1482
  auto params = ctx->programParameter();
12✔
1483
  for ( size_t i = 0; i < params.size(); ++i )
26✔
1484
  {
1485
    visitProgramParameter( params[i] );
14✔
1486
    // comma is optional here
1487
    if ( i < params.size() - 1 && ctx->COMMA( i ) )
14✔
1488
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() | FmtToken::PREFERRED_BREAK );
2✔
1489
  }
1490
  return !params.empty();
24✔
1491
}
12✔
1492

1493
antlrcpp::Any PrettifyFileProcessor::visitProgramParameters(
73✔
1494
    EscriptParser::ProgramParametersContext* ctx )
1495
{
1496
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle() );
73✔
1497

1498
  bool args = false;
73✔
1499
  if ( auto programParameterList = ctx->programParameterList() )
73✔
1500
    args = std::any_cast<bool>( visitProgramParameterList( programParameterList ) );
12✔
1501

1502
  addToken( ")", ctx->RPAREN(), linebuilder.closingParenthesisStyle( args ) );
73✔
1503
  return {};
73✔
1504
}
1505

1506
antlrcpp::Any PrettifyFileProcessor::visitProgramParameter(
14✔
1507
    EscriptParser::ProgramParameterContext* ctx )
1508
{
1509
  if ( auto unused = ctx->UNUSED() )
14✔
1510
    addToken( "unused", unused, FmtToken::SPACE );
2✔
1511

1512
  make_identifier( ctx->IDENTIFIER() );
14✔
1513
  if ( auto expression = ctx->expression() )
14✔
1514
  {
1515
    addToken( ":=", ctx->ASSIGN(), linebuilder.assignmentStyle() );
×
1516
    visitExpression( expression );
×
1517
  }
1518
  return {};
14✔
1519
}
1520

1521
antlrcpp::Any PrettifyFileProcessor::visitStatement( EscriptParser::StatementContext* ctx )
6,086✔
1522
{
1523
  if ( auto ifStatement = ctx->ifStatement() )
6,086✔
1524
    return visitIfStatement( ifStatement );
261✔
1525
  if ( auto gotoStatement = ctx->gotoStatement() )
5,825✔
1526
    return visitGotoStatement( gotoStatement );
×
1527
  if ( auto returnStatement = ctx->returnStatement() )
5,825✔
1528
    return visitReturnStatement( returnStatement );
208✔
1529
  if ( auto constStatement = ctx->constStatement() )
5,617✔
1530
    return visitConstStatement( constStatement );
65✔
1531
  if ( auto varStatement = ctx->varStatement() )
5,552✔
1532
    return visitVarStatement( varStatement );
883✔
1533
  if ( auto doStatement = ctx->doStatement() )
4,669✔
1534
    return visitDoStatement( doStatement );
5✔
1535
  if ( auto whileStatement = ctx->whileStatement() )
4,664✔
1536
    return visitWhileStatement( whileStatement );
45✔
1537
  if ( auto exitStatement = ctx->exitStatement() )
4,619✔
1538
    return visitExitStatement( exitStatement );
6✔
1539
  if ( auto breakStatement = ctx->breakStatement() )
4,613✔
1540
    return visitBreakStatement( breakStatement );
44✔
1541
  if ( auto continueStatement = ctx->continueStatement() )
4,569✔
1542
    return visitContinueStatement( continueStatement );
28✔
1543
  if ( auto forStatement = ctx->forStatement() )
4,541✔
1544
    return visitForStatement( forStatement );
35✔
1545
  if ( auto foreachStatement = ctx->foreachStatement() )
4,506✔
1546
    return visitForeachStatement( foreachStatement );
86✔
1547
  if ( auto repeatStatement = ctx->repeatStatement() )
4,420✔
1548
    return visitRepeatStatement( repeatStatement );
15✔
1549
  if ( auto caseStatement = ctx->caseStatement() )
4,405✔
1550
    return visitCaseStatement( caseStatement );
28✔
1551
  if ( auto enumStatement = ctx->enumStatement() )
4,377✔
1552
    return visitEnumStatement( enumStatement );
13✔
1553
  if ( auto expression = ctx->statementExpression )
4,364✔
1554
  {
1555
    visitExpression( expression );
4,364✔
1556

1557
    addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
4,364✔
1558
    _currentscope &= ~FmtToken::Scope::VAR;  // matches with assignment inside of visitExpression
4,364✔
1559
    linebuilder.buildLine( _currindent );
4,364✔
1560
    return {};
4,364✔
1561
  }
1562

1563
  return {};
×
1564
}
1565

1566
antlrcpp::Any PrettifyFileProcessor::visitStringIdentifier(
83✔
1567
    EscriptParser::StringIdentifierContext* ctx )
1568
{
1569
  if ( auto identifier = ctx->IDENTIFIER() )
83✔
1570
    return make_identifier( identifier );
30✔
1571
  if ( auto string_literal = ctx->STRING_LITERAL() )
53✔
1572
    return make_string_literal( string_literal );
53✔
1573
  return {};
×
1574
}
1575

1576
antlrcpp::Any PrettifyFileProcessor::visitStructInitializerExpression(
166✔
1577
    EscriptParser::StructInitializerExpressionContext* ctx )
1578
{
1579
  if ( auto identifier = ctx->IDENTIFIER() )
166✔
1580
    make_identifier( identifier );
156✔
1581
  else if ( auto string_literal = ctx->STRING_LITERAL() )
10✔
1582
    make_string_literal( string_literal );
7✔
1583

1584
  if ( auto expression = ctx->expression() )
166✔
1585
  {
1586
    if ( auto assign = ctx->ASSIGN() )
150✔
1587
      addToken( ":=", assign, linebuilder.assignmentStyle() );
147✔
1588

1589
    visitExpression( expression );
150✔
1590

1591
    if ( ctx->ELLIPSIS() )
150✔
1592
    {
1593
      addToken( "...", ctx->ELLIPSIS(), linebuilder.ellipsisStyle() );
3✔
1594
    }
1595
  }
1596

1597
  return {};
166✔
1598
}
1599

1600
antlrcpp::Any PrettifyFileProcessor::visitUseDeclaration(
28✔
1601
    EscriptParser::UseDeclarationContext* ctx )
1602
{
1603
  addToken( "use", ctx->USE(), FmtToken::SPACE );
28✔
1604
  visitStringIdentifier( ctx->stringIdentifier() );
28✔
1605
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
28✔
1606

1607
  linebuilder.buildLine( _currindent );
28✔
1608
  return {};
28✔
1609
}
1610

1611
antlrcpp::Any PrettifyFileProcessor::make_statement_label(
214✔
1612
    EscriptParser::StatementLabelContext* ctx )
1613
{
1614
  if ( ctx )
214✔
1615
  {
1616
    make_identifier( ctx->IDENTIFIER() );
14✔
1617
    addToken( ":", ctx->COLON(), FmtToken::SPACE | FmtToken::ATTACHED );
14✔
1618
  }
1619
  return {};
214✔
1620
}
1621

1622
antlrcpp::Any PrettifyFileProcessor::make_identifier( antlr4::tree::TerminalNode* terminal )
12,345✔
1623
{
1624
  addToken( terminal->getText(), terminal, FmtToken::SPACE );
12,345✔
1625
  return {};
12,345✔
1626
}
1627

1628
antlrcpp::Any PrettifyFileProcessor::make_string_literal( antlr4::tree::TerminalNode* terminal )
2,770✔
1629
{
1630
  addToken( terminal->getText(), terminal, FmtToken::SPACE );
2,770✔
1631
  return {};
2,770✔
1632
}
1633

1634
antlrcpp::Any PrettifyFileProcessor::make_integer_literal( antlr4::tree::TerminalNode* terminal )
2,637✔
1635
{
1636
  addToken( terminal->getText(), terminal, FmtToken::SPACE );
2,637✔
1637
  return {};
2,637✔
1638
}
1639

1640
antlrcpp::Any PrettifyFileProcessor::make_float_literal( antlr4::tree::TerminalNode* terminal )
224✔
1641
{
1642
  addToken( terminal->getText(), terminal, FmtToken::SPACE );
224✔
1643
  return {};
224✔
1644
}
1645

1646
antlrcpp::Any PrettifyFileProcessor::make_bool_literal( antlr4::tree::TerminalNode* terminal )
105✔
1647
{
1648
  addToken( terminal->getText(), terminal, FmtToken::SPACE );
105✔
1649
  return {};
105✔
1650
}
1651

1652
antlrcpp::Any PrettifyFileProcessor::make_regular_expression_literal(
50✔
1653
    antlr4::tree::TerminalNode* terminal )
1654
{
1655
  addToken( terminal->getText(), terminal, FmtToken::SPACE );
50✔
1656
  return {};
50✔
1657
}
1658

1659
void PrettifyFileProcessor::addToken( std::string&& text, const Position& pos, int style,
51,304✔
1660
                                      size_t token_type, FmtContext context )
1661
{
1662
  linebuilder.addPart( { std::forward<std::string>( text ), pos, style, _currentgroup, token_type,
51,304✔
1663
                         context, _currentscope } );
1664
}
51,304✔
1665
void PrettifyFileProcessor::addToken( std::string&& text, antlr4::tree::TerminalNode* terminal,
48,009✔
1666
                                      int style, FmtContext context )
1667
{
1668
  if ( compilercfg.FormatterKeepKeywords )
48,009✔
1669
    addToken( terminal->getSymbol()->getText(), Range( *terminal ).start, style,
×
1670
              terminal->getSymbol()->getType(), context );
×
1671
  else
1672
    addToken( std::forward<std::string>( text ), Range( *terminal ).start, style,
48,009✔
1673
              terminal->getSymbol()->getType(), context );
48,009✔
1674
}
48,009✔
1675
void PrettifyFileProcessor::addToken( std::string&& text, antlr4::Token* token, int style,
2,853✔
1676
                                      FmtContext context )
1677
{
1678
  if ( compilercfg.FormatterKeepKeywords )
2,853✔
1679
    addToken( token->getText(), Range( token ).start, style, token->getType(), context );
×
1680
  else
1681
    addToken( std::forward<std::string>( text ), Range( token ).start, style, token->getType(),
2,853✔
1682
              context );
1683
}
2,853✔
1684

1685
void PrettifyFileProcessor::preprocess( SourceFile& sf )
660✔
1686
{
1687
  auto rawlines = load_raw_file();
660✔
1688
  auto comments = collectComments( sf );
660✔
1689
  std::vector<Range> skiplines;
660✔
1690
  for ( const auto& c : comments )
1,639✔
1691
  {
1692
    if ( c.text.find( "format-off" ) != std::string::npos )
979✔
1693
      skiplines.emplace_back( c.pos, c.pos );
6✔
1694
    else if ( c.text.find( "format-on" ) != std::string::npos )
973✔
1695
      if ( !skiplines.empty() )
×
1696
        skiplines.back().end = c.pos_end;
×
1697
  }
1698
  if ( !skiplines.empty() )
660✔
1699
  {
1700
    // set unmatched end to file eof
1701
    if ( skiplines.back().start.line_number == skiplines.back().end.line_number )
6✔
1702
      skiplines.back().end.line_number = rawlines.size() + 1;
6✔
1703
  }
1704

1705
  // remove all comments between noformat ranges
1706
  comments.erase( std::remove_if( comments.begin(), comments.end(),
660✔
1707
                                  [&]( auto& c )
979✔
1708
                                  {
1709
                                    for ( const auto& s : skiplines )
983✔
1710
                                    {
1711
                                      if ( s.start.line_number <= c.pos.line_number &&
36✔
1712
                                           s.end.line_number >= c.pos.line_number )
32✔
1713
                                        return true;
32✔
1714
                                    }
1715
                                    return false;
947✔
1716
                                  } ),
1717
                  comments.end() );
660✔
1718
  linebuilder.setComments( std::move( comments ) );
660✔
1719
  linebuilder.setSkipLines( std::move( skiplines ) );
660✔
1720
  linebuilder.setRawLines( std::move( rawlines ) );
660✔
1721
}
660✔
1722

1723
std::vector<std::string> PrettifyFileProcessor::load_raw_file()
660✔
1724
{
1725
  Clib::FileContents fc( source_file_identifier.pathname.c_str(), true );
660✔
1726
  const auto& contents = fc.str_contents();
660✔
1727
  std::vector<std::string> rawlines;
660✔
1728
  std::string currline;
660✔
1729
  for ( size_t i = 0; i < contents.size(); ++i )
226,883✔
1730
  {
1731
    if ( contents[i] == '\r' && i + 1 < contents.size() && contents[i + 1] == '\n' )
226,223✔
1732
    {
1733
      ++i;
×
1734
      rawlines.emplace_back( std::move( currline ) );
×
1735
      currline.clear();
×
1736
      continue;
×
1737
    }
1738
    if ( contents[i] == '\r' || contents[i] == '\n' )
226,223✔
1739
    {
1740
      rawlines.emplace_back( std::move( currline ) );
11,002✔
1741
      currline.clear();
11,002✔
1742
    }
1743
    else
1744
      currline += contents[i];
215,221✔
1745
  }
1746
  if ( !currline.empty() )
660✔
1747
    rawlines.emplace_back( std::move( currline ) );
2✔
1748
  return rawlines;
1,320✔
1749
}
660✔
1750

1751
std::vector<FmtToken> PrettifyFileProcessor::collectComments( SourceFile& sf )
660✔
1752
{
1753
  auto alltokens = sf.get_all_tokens();
660✔
1754
  std::vector<FmtToken> comments;
660✔
1755
  for ( size_t i = 0; i < alltokens.size(); ++i )
85,662✔
1756
  {
1757
    const auto& comment = alltokens[i];
85,002✔
1758
    if ( comment->getType() == EscriptLexer::COMMENT ||
169,970✔
1759
         comment->getType() == EscriptLexer::LINE_COMMENT )
84,968✔
1760
    {
1761
      Range startpos( comment );
979✔
1762
      Range endpos( comment );
979✔
1763

1764
      // use whitespace token as start if its on the same line
1765
      // so that the tokenid of a comment is always the next tokenid after a "actual" token
1766
      if ( i > 0 )
979✔
1767
      {
1768
        if ( alltokens[i - 1]->getType() == EscriptLexer::WS &&
1,674✔
1769
             alltokens[i - 1]->getLine() == startpos.start.line_number )
837✔
1770
          startpos = Range( alltokens[i - 1] );
315✔
1771
      }
1772
      FmtToken info;
979✔
1773
      info.text = comment->getText();
979✔
1774
      info.token_type = comment->getType();
979✔
1775
      info.style = FmtToken::SPACE;
979✔
1776
      // replace tabs with spaces if not active
1777
      if ( compilercfg.FormatterFormatInsideComments && !compilercfg.FormatterUseTabs )
979✔
1778
      {
1779
        auto it = info.text.find( '\t' );
979✔
1780
        while ( it != std::string::npos )
979✔
1781
        {
1782
          // replacing tabs inbetween is a bit more complicated...
1783
          // the size is based on the next tabstop which is eg 4
1784
          // if its multiline we need to calc it based on the last newline
1785
          auto lastnewline = info.text.find_last_of( '\n', it );
×
1786
          if ( lastnewline == std::string::npos )
×
1787
            lastnewline = 0;
×
1788
          auto delta = ( it - lastnewline ) % compilercfg.FormatterTabWidth;
×
1789
          info.text.replace( it, 1, std::string( compilercfg.FormatterTabWidth - delta, ' ' ) );
×
1790
          it = info.text.find( '\t' );
×
1791
        }
1792
      }
1793
      if ( info.token_type == EscriptLexer::LINE_COMMENT )
979✔
1794
      {
1795
        info.context = FmtContext::LINE_COMMENT;
945✔
1796
        info.style |= FmtToken::FORCED_BREAK;
945✔
1797
        if ( compilercfg.FormatterFormatInsideComments )
945✔
1798
        {
1799
          info.text.erase( 0, 2 );  // remove //
945✔
1800
          auto firstchar = info.text.find_first_not_of( " \t" );
945✔
1801
          if ( info.text.empty() || firstchar == std::string::npos )
945✔
1802
          {
1803
            // empty or only whitespace
1804
            info.text = "//";
42✔
1805
          }
1806
          else if ( info.text.front() == '/' )
903✔
1807
          {
1808
            // assuming its ////// -> keep it
1809
            info.text = std::string( "//" ) + info.text;
4✔
1810
          }
1811
          else
1812
          {
1813
            // add space if non is there
1814
            if ( info.text.front() != ' ' )
899✔
1815
              info.text = std::string( "// " ) + info.text;
×
1816
            else
1817
              info.text = std::string( "//" ) + info.text;
899✔
1818
          }
1819
          auto lastchar = info.text.find_last_not_of( ' ' );
945✔
1820
          info.text.erase( info.text.begin() + lastchar + 1, info.text.end() );
945✔
1821
        }
1822
      }
1823
      else
1824
      {
1825
        info.context = FmtContext::COMMENT;
34✔
1826
        if ( compilercfg.FormatterFormatInsideComments )
34✔
1827
        {
1828
          info.text.erase( 0, 2 );                                  // remove /*
34✔
1829
          info.text.erase( info.text.end() - 2, info.text.end() );  // remove */
34✔
1830
          auto firstchar = info.text.find_first_not_of( " \t" );
34✔
1831
          // remove remaining whitespace
1832
          info.text.erase( 0, firstchar );
34✔
1833
          auto lastchar = info.text.find_last_not_of( " \t" );
34✔
1834
          info.text.erase( info.text.begin() + lastchar + 1, info.text.end() );
34✔
1835
          if ( info.text.empty() )
34✔
1836
            info.text = std::string( "/*" ) + info.text + "*/";
×
1837
          else
1838
          {
1839
            std::string text = "/*";
34✔
1840
            // if its in the style of "/** blubb" or "/*\n"  dont add whitespace
1841
            if ( info.text.front() != '\n' && info.text.front() != '\r' &&
65✔
1842
                 info.text.front() != '*' )
31✔
1843
              text += ' ';
10✔
1844
            text += info.text;
34✔
1845
            // if its in the style of "blubb **/" or "\n*/"  dont add whitespace
1846
            if ( info.text.back() != '\n' && info.text.back() != '\r' && info.text.back() != '*' )
34✔
1847
              text += ' ';
10✔
1848

1849
            // detect aligned "*/"
1850
            // /*
1851
            //  *
1852
            //  */
1853
            if ( info.text.back() == '\n' || info.text.back() == '\r' )
34✔
1854
            {
1855
              auto lastnewline = text.find_last_of( "\n\r", text.size() - 2 );
3✔
1856
              if ( lastnewline != std::string::npos && lastnewline + 2 < text.size() )
3✔
1857
              {
1858
                if ( text[lastnewline + 1] == ' ' && text[lastnewline + 2] == '*' )
1✔
1859
                  text += ' ';
×
1860
              }
1861
            }
1862
            text += "*/";
34✔
1863
            info.text = text;
34✔
1864
          }
34✔
1865
        }
1866
        // split lines to use correct linenendings
1867
        std::string rawtext = std::move( info.text );
34✔
1868
        info.text.clear();
34✔
1869
        for ( size_t ri = 0; ri < rawtext.size(); ++ri )
3,452✔
1870
        {
1871
          if ( rawtext[ri] == '\r' && ri + 1 < rawtext.size() && rawtext[ri + 1] == '\n' )
3,418✔
1872
          {
1873
            ++ri;
×
1874
            auto lastchar = info.text.find_last_not_of( ' ' );
×
1875
            info.text.erase( info.text.begin() + lastchar + 1, info.text.end() );
×
1876
            info.text += compilercfg.FormatterWindowsLineEndings ? "\r\n" : "\n";
×
1877
          }
1878
          else if ( rawtext[ri] == '\r' || rawtext[ri] == '\n' )
3,418✔
1879
          {
1880
            auto lastchar = info.text.find_last_not_of( ' ' );
136✔
1881
            info.text.erase( info.text.begin() + lastchar + 1, info.text.end() );
136✔
1882
            info.text += compilercfg.FormatterWindowsLineEndings ? "\r\n" : "\n";
136✔
1883
          }
1884
          else
1885
            info.text += rawtext[ri];
3,282✔
1886
        }
1887
      }
34✔
1888
      info.pos = startpos.start;
979✔
1889
      info.pos_end = endpos.end;
979✔
1890
      comments.emplace_back( std::move( info ) );
979✔
1891
    }
979✔
1892
  }
1893
  return comments;
1,320✔
1894
}
660✔
1895
}  // namespace Pol::Bscript::Compiler
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc