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

polserver / polserver / 39488504183

20 Oct 2026 08:01PM UTC coverage: 81.209% (-0.8%) from 81.995%
39488504183

Pull #991

github

turleypol
use python interpreter from configure step
Pull Request #991: Ecompile diagnostics for vscode

281 of 1037 new or added lines in 43 files covered. (27.1%)

24 existing lines in 11 files now uncovered.

60426 of 74408 relevant lines covered (81.21%)

788778.95 hits per line

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

89.58
/pol-core/bscript/compiler/file/PrettifyFileProcessor.cpp
1
#include "bscript/compiler/file/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/compiler/file/SourceFileLoader.h"
10
#include "bscript/compilercfg.h"
11
#include "clib/filecont.h"
12
#include "clib/logfacility.h"
13

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

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

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

83
PrettifyFileProcessor::PrettifyFileProcessor( const SourceFileIdentifier& source_file_identifier,
710 ✔
84
                                              SourceFileLoader& source_loader, Profile& /*profile*/,
85
                                              Report& report )
710 ✔
86
    : source_file_identifier( source_file_identifier ) /*, profile( profile )*/,
710 ✔
87
      source_loader( source_loader ),
710 ✔
88
      report( report )
710 ✔
89
{
90
}
710 ✔
91

92
antlrcpp::Any PrettifyFileProcessor::process_compilation_unit( SourceFile& sf,
710 ✔
93
                                                               std::optional<Range> format_range )
94
{
95
  if ( auto compilation_unit = sf.get_compilation_unit( report, source_file_identifier ) )
710 ✔
96
  {
97
    if ( report.error_count() )
710 ✔
98
      return {};
×
99
    preprocess( sf, format_range );
710 ✔
100
    return compilation_unit->accept( this );
710 ✔
101
  }
102
  throw std::runtime_error( "No compilation unit in source file" );
×
103
}
104

NEW
105
antlrcpp::Any PrettifyFileProcessor::process_module_unit( SourceFile& sf,
×
106
                                                          std::optional<Range> format_range )
107
{
108
  if ( auto module_unit = sf.get_module_unit( report, source_file_identifier ) )
×
109
  {
110
    if ( report.error_count() )
×
111
      return {};
×
NEW
112
    preprocess( sf, format_range );
×
113
    return module_unit->accept( this );
×
114
  }
115
  throw std::runtime_error( "No compilation unit in source file" );
×
116
}
117

118
antlrcpp::Any PrettifyFileProcessor::visitCompilationUnit(
710 ✔
119
    EscriptParser::CompilationUnitContext* ctx )
120
{
121
  visitChildren( ctx );
710 ✔
122
  if ( !linebuilder.finalize() )
710 ✔
123
    report.error( source_file_identifier, "left over formatting lines: {}",
×
124
                  linebuilder.currentTokens() );
125
  return {};
710 ✔
126
}
127

128
antlrcpp::Any PrettifyFileProcessor::visitModuleUnit( EscriptParser::ModuleUnitContext* ctx )
×
129
{
130
  visitChildren( ctx );
×
131
  if ( !linebuilder.finalize() )
×
132
    report.error( source_file_identifier, "left over formatting lines: {}",
×
133
                  linebuilder.currentTokens() );
134
  return {};
×
135
}
136

137

138
std::string PrettifyFileProcessor::prettify() const
710 ✔
139
{
140
  auto result =
141
      fmt::format( "{}", fmt::join( linebuilder.formattedLines(),
1,420 ✔
142
                                    compilercfg.FormatterWindowsLineEndings ? "\r\n" : "\n" ) );
1,420 ✔
143
  if ( result.empty() )
710 ✔
144
  {
145
    report.error( source_file_identifier, "formatting result is empty" );
×
146
    return {};
×
147
  }
148
  return result;
710 ✔
149
}
710 ✔
150

151

152
antlrcpp::Any PrettifyFileProcessor::visitVarStatement( EscriptParser::VarStatementContext* ctx )
1,105 ✔
153
{
154
  _currentscope |= FmtToken::Scope::VAR;
1,105 ✔
155
  addToken( "var", ctx->VAR(), FmtToken::SPACE, FmtContext::VAR_STATEMENT );
2,210 ✔
156
  visitVariableDeclarationList( ctx->variableDeclarationList() );
1,105 ✔
157
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
2,210 ✔
158
  _currentscope &= ~FmtToken::Scope::VAR;
1,105 ✔
159
  linebuilder.buildLine( _currindent );
1,105 ✔
160
  return {};
1,105 ✔
161
}
162

163
antlrcpp::Any PrettifyFileProcessor::visitParExpression( EscriptParser::ParExpressionContext* ctx )
719 ✔
164
{
165
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle() & ~FmtToken::ATTACHED );
1,438 ✔
166
  auto args = std::any_cast<bool>( visitExpression( ctx->expression() ) );
719 ✔
167
  addToken( ")", ctx->RPAREN(), linebuilder.closingParenthesisStyle( args ) );
1,438 ✔
168
  return {};
719 ✔
169
}
170

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

186
  visitBlock( ctx->block() );
45 ✔
187
  addToken( "endwhile", ctx->ENDWHILE(), FmtToken::SPACE );
90 ✔
188
  linebuilder.buildLine( _currindent );
45 ✔
189
  return {};
45 ✔
190
}
191

192
antlrcpp::Any PrettifyFileProcessor::visitVariableDeclarationList(
1,105 ✔
193
    EscriptParser::VariableDeclarationListContext* ctx )
194
{
195
  auto args = ctx->variableDeclaration();
1,105 ✔
196
  for ( size_t i = 0; i < args.size(); ++i )
2,283 ✔
197
  {
198
    visitVariableDeclaration( args[i] );
1,178 ✔
199
    if ( i < args.size() - 1 )
1,178 ✔
200
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle(), FmtContext::VAR_COMMA );
219 ✔
201
  }
202
  return {};
2,210 ✔
203
}
1,105 ✔
204
antlrcpp::Any PrettifyFileProcessor::visitVariableDeclaration(
1,178 ✔
205
    EscriptParser::VariableDeclarationContext* ctx )
206
{
207
  if ( auto identifier = ctx->IDENTIFIER() )
1,178 ✔
208
  {
209
    make_identifier( identifier );
1,133 ✔
210

211
    if ( auto variable_declaration_initializer = ctx->variableDeclarationInitializer() )
1,133 ✔
212
    {
213
      _currentscope |= FmtToken::Scope::VAR;
978 ✔
214

215
      if ( auto assign = variable_declaration_initializer->ASSIGN() )
978 ✔
216
        addToken( ":=", assign, linebuilder.assignmentStyle() );
2,862 ✔
217

218
      if ( auto expression = variable_declaration_initializer->expression() )
978 ✔
219
        visitExpression( expression );
954 ✔
220
      else if ( auto arr = variable_declaration_initializer->ARRAY() )
24 ✔
221
        addToken( "array", arr, FmtToken::SPACE );
48 ✔
222
      _currentscope &= ~FmtToken::Scope::VAR;
978 ✔
223
    }
224
  }
225
  else if ( ctx->bindingDeclaration() )
45 ✔
226
  {
227
    _currentscope |= FmtToken::Scope::VAR;
45 ✔
228
    visitChildren( ctx );
45 ✔
229
    _currentscope &= ~FmtToken::Scope::VAR;
45 ✔
230
  }
231

232
  return {};
1,178 ✔
233
}
234

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

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

272
  return {};
59 ✔
273
}
274

275
antlrcpp::Any PrettifyFileProcessor::visitBindingDeclarationInitializer(
45 ✔
276
    EscriptGrammar::EscriptParser::BindingDeclarationInitializerContext* ctx )
277
{
278
  addToken( ":=", ctx->ASSIGN(), linebuilder.assignmentStyle() );
90 ✔
279
  visitExpression( ctx->expression() );
45 ✔
280

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

291
    if ( i < args.size() - 1 )
62 ✔
292
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() );
108 ✔
293
  }
294

295
  return {};
52 ✔
296
}
26 ✔
297

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

309
  return {};
66 ✔
310
}
33 ✔
311

312
antlrcpp::Any PrettifyFileProcessor::visitIndexBinding(
62 ✔
313
    EscriptGrammar::EscriptParser::IndexBindingContext* ctx )
314
{
315
  if ( auto identifier = ctx->IDENTIFIER() )
62 ✔
316
  {
317
    make_identifier( identifier );
57 ✔
318
  }
319

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

333
  if ( auto binding = ctx->binding() )
62 ✔
334
  {
335
    visitBinding( binding );
25 ✔
336
  }
337

338
  return {};
62 ✔
339
}
340

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

352
  if ( auto identifier = ctx->IDENTIFIER() )
25 ✔
353
  {
354
    make_identifier( identifier );
16 ✔
355
  }
356
  else if ( auto binding_decl = ctx->bindingDeclaration() )
9 ✔
357
  {
358
    visitBindingDeclaration( binding_decl );
9 ✔
359
  }
360

361
  return {};
25 ✔
362
}
363

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

380
  return {};
102 ✔
381
}
382

383
antlrcpp::Any PrettifyFileProcessor::visitConstStatement(
77 ✔
384
    EscriptParser::ConstStatementContext* ctx )
385
{
386
  addToken( "const", ctx->TOK_CONST(), FmtToken::SPACE );
154 ✔
387
  auto const_declaration_ctx = ctx->constantDeclaration();
77 ✔
388
  make_identifier( const_declaration_ctx->IDENTIFIER() );
77 ✔
389

390
  if ( auto variable_declaration_initializer =
77 ✔
391
           const_declaration_ctx->variableDeclarationInitializer() )
77 ✔
392
  {
393
    if ( auto assign = variable_declaration_initializer->ASSIGN() )
77 ✔
394
      addToken( ":=", assign, linebuilder.assignmentStyle() );
231 ✔
395
    if ( auto expression = variable_declaration_initializer->expression() )
77 ✔
396
      visitExpression( expression );
77 ✔
397
    else if ( auto array = variable_declaration_initializer->ARRAY() )
×
398
      addToken( "array", array, FmtToken::SPACE );
×
399
  }
400
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
154 ✔
401

402
  linebuilder.buildLine( _currindent );
77 ✔
403
  return {};
77 ✔
404
}
405

406
antlrcpp::Any PrettifyFileProcessor::visitDictInitializerExpression(
62 ✔
407
    EscriptParser::DictInitializerExpressionContext* ctx )
408
{
409
  visitExpression( ctx->expression( 0 ) );  // key
62 ✔
410

411
  if ( ctx->ELLIPSIS() )
62 ✔
412
  {
413
    addToken( "...", ctx->ELLIPSIS(), linebuilder.ellipsisStyle() );
15 ✔
414
  }
415
  else
416
  {
417
    if ( ctx->expression().size() > 1 )
57 ✔
418
    {
419
      addToken( "->", ctx->ARROW(),
108 ✔
420
                linebuilder.delimiterStyle() & ~FmtToken::BREAKPOINT & ~FmtToken::ATTACHED );
54 ✔
421
      visitExpression( ctx->expression( 1 ) );
54 ✔
422
    }
423
  }
424
  return {};
62 ✔
425
}
426

427
antlrcpp::Any PrettifyFileProcessor::visitDoStatement( EscriptParser::DoStatementContext* ctx )
7 ✔
428
{
429
  make_statement_label( ctx->statementLabel() );
7 ✔
430
  addToken( "do", ctx->DO(), FmtToken::SPACE | FmtToken::BREAKPOINT );
14 ✔
431
  linebuilder.buildLine( _currindent );
7 ✔
432

433
  visitBlock( ctx->block() );
7 ✔
434

435
  addToken( "dowhile", ctx->DOWHILE(), FmtToken::SPACE );
14 ✔
436
  visitParExpression( ctx->parExpression() );
7 ✔
437
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
14 ✔
438
  linebuilder.buildLine( _currindent );
7 ✔
439
  return {};
7 ✔
440
}
441

442
antlrcpp::Any PrettifyFileProcessor::visitEnumListEntry( EscriptParser::EnumListEntryContext* ctx )
40 ✔
443
{
444
  make_identifier( ctx->IDENTIFIER() );
40 ✔
445

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

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

463
    linebuilder.buildLine( _currindent );
40 ✔
464
  }
465
  return {};
26 ✔
466
}
13 ✔
467

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

481
  addToken( "endenum", ctx->ENDENUM(), FmtToken::SPACE );
26 ✔
482
  linebuilder.buildLine( _currindent );
13 ✔
483
  return {};
26 ✔
484
}
13 ✔
485

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

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

508
  if ( auto rbrace = ctx->RBRACE() )
162 ✔
509
    addToken( "}", rbrace, linebuilder.closingBracketStyle( curcount ) );
474 ✔
510
  else if ( auto rparen = ctx->RPAREN() )
4 ✔
511
    addToken( ")", rparen, linebuilder.closingParenthesisStyle( args ) );
12 ✔
512
  return {};
162 ✔
513
}
514

515
antlrcpp::Any PrettifyFileProcessor::visitExplicitArrayInitializer(
166 ✔
516
    EscriptParser::ExplicitArrayInitializerContext* ctx )
517
{
518
  ++_currentgroup;
166 ✔
519
  _currentscope |= FmtToken::Scope::ARRAY;
166 ✔
520
  addToken( "array", ctx->ARRAY(), FmtToken::SPACE );
332 ✔
521
  if ( auto init = ctx->arrayInitializer() )
166 ✔
522
    visitArrayInitializer( init );
162 ✔
523
  _currentscope &= ~FmtToken::Scope::ARRAY;
166 ✔
524
  --_currentgroup;
166 ✔
525
  return {};
166 ✔
526
}
527

528
antlrcpp::Any PrettifyFileProcessor::visitDictInitializerExpressionList(
34 ✔
529
    EscriptParser::DictInitializerExpressionListContext* ctx )
530
{
531
  auto inits = ctx->dictInitializerExpression();
34 ✔
532
  ++_currentgroup;
34 ✔
533
  for ( size_t i = 0; i < inits.size(); ++i )
96 ✔
534
  {
535
    visitDictInitializerExpression( inits[i] );
62 ✔
536
    if ( i < inits.size() - 1 )
62 ✔
537
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() );
84 ✔
538
  }
539
  --_currentgroup;
34 ✔
540
  return {};
68 ✔
541
}
34 ✔
542

543
antlrcpp::Any PrettifyFileProcessor::visitDictInitializer(
50 ✔
544
    EscriptParser::DictInitializerContext* ctx )
545
{
546
  addToken( "{", ctx->LBRACE(), linebuilder.openingBracketStyle( true ) );
100 ✔
547
  size_t curcount = linebuilder.currentTokens().size();
50 ✔
548
  if ( auto expr = ctx->dictInitializerExpressionList() )
50 ✔
549
    visitDictInitializerExpressionList( expr );
34 ✔
550

551
  addToken( "}", ctx->RBRACE(), linebuilder.closingBracketStyle( curcount ) );
100 ✔
552
  return {};
50 ✔
553
}
554

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

568
antlrcpp::Any PrettifyFileProcessor::visitStructInitializerExpressionList(
101 ✔
569
    EscriptParser::StructInitializerExpressionListContext* ctx )
570
{
571
  auto inits = ctx->structInitializerExpression();
101 ✔
572
  for ( size_t i = 0; i < inits.size(); ++i )
298 ✔
573
  {
574
    visitStructInitializerExpression( inits[i] );
197 ✔
575
    if ( i < inits.size() - 1 )
197 ✔
576
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() );
288 ✔
577
  }
578
  return {};
202 ✔
579
}
101 ✔
580

581
antlrcpp::Any PrettifyFileProcessor::visitStructInitializer(
126 ✔
582
    EscriptParser::StructInitializerContext* ctx )
583
{
584
  addToken( "{", ctx->LBRACE(), linebuilder.openingBracketStyle( true ) );
252 ✔
585
  ++_currentgroup;
126 ✔
586
  size_t curcount = linebuilder.currentTokens().size();
126 ✔
587
  if ( auto expr = ctx->structInitializerExpressionList() )
126 ✔
588
    visitStructInitializerExpressionList( expr );
101 ✔
589
  --_currentgroup;
126 ✔
590

591
  addToken( "}", ctx->RBRACE(), linebuilder.closingBracketStyle( curcount ) );
252 ✔
592
  return {};
126 ✔
593
}
594

595
antlrcpp::Any PrettifyFileProcessor::visitExplicitErrorInitializer(
19 ✔
596
    EscriptParser::ExplicitErrorInitializerContext* ctx )
597
{
598
  addToken( "error", ctx->TOK_ERROR(), FmtToken::SPACE );
38 ✔
599
  if ( auto init = ctx->structInitializer() )
19 ✔
600
    visitStructInitializer( init );
15 ✔
601
  return {};
19 ✔
602
}
603

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

619
antlrcpp::Any PrettifyFileProcessor::visitExplicitStructInitializer(
125 ✔
620
    EscriptParser::ExplicitStructInitializerContext* ctx )
621
{
622
  ++_currentgroup;
125 ✔
623
  _currentscope |= FmtToken::Scope::STRUCT;
125 ✔
624
  addToken( "struct", ctx->STRUCT(), FmtToken::SPACE );
250 ✔
625
  if ( auto init = ctx->structInitializer() )
125 ✔
626
    visitStructInitializer( init );
111 ✔
627
  _currentscope &= ~FmtToken::Scope::STRUCT;
125 ✔
628
  --_currentgroup;
125 ✔
629
  return {};
125 ✔
630
}
631

632
antlrcpp::Any PrettifyFileProcessor::visitExpressionList(
6,718 ✔
633
    EscriptParser::ExpressionListContext* ctx )
634
{
635
  auto args = ctx->expressionListEntry();
6,718 ✔
636
  for ( size_t i = 0; i < args.size(); ++i )
16,342 ✔
637
  {
638
    visitExpression( args[i]->expression() );
9,624 ✔
639

640
    if ( args[i]->ELLIPSIS() )
9,624 ✔
641
      addToken( "...", args[i]->ELLIPSIS(), linebuilder.ellipsisStyle() );
603 ✔
642

643
    if ( i < args.size() - 1 )
9,624 ✔
644
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() | FmtToken::PREFERRED_BREAK );
8,718 ✔
645
  }
646
  return !args.empty();
13,436 ✔
647
}
6,718 ✔
648

649
antlrcpp::Any PrettifyFileProcessor::visitIndexList( EscriptParser::IndexListContext* ctx )
510 ✔
650
{
651
  auto args = ctx->expression();
510 ✔
652
  for ( size_t i = 0; i < args.size(); ++i )
1,085 ✔
653
  {
654
    visitExpression( args[i] );
575 ✔
655
    if ( i < args.size() - 1 )
575 ✔
656
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() | FmtToken::PREFERRED_BREAK );
195 ✔
657
  }
658
  return {};
1,020 ✔
659
}
510 ✔
660

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

742
    visitExpression( ctx->expression( 1 ) );  // right
5,021 ✔
743
    return true;
5,021 ✔
744
  }
745
  if ( auto suffix = ctx->expressionSuffix() )
1,882 ✔
746
  {
747
    expression_suffix( ctx->expression( 0 ), suffix );
1,847 ✔
748
    return true;
1,847 ✔
749
  }
750
  if ( ctx->QUESTION() )
35 ✔
751
  {
752
    visitExpression( ctx->expression( 0 ) );  // conditional
35 ✔
753
    addToken( "?", ctx->QUESTION(), FmtToken::SPACE | FmtToken::BREAKPOINT );
70 ✔
754
    visitExpression( ctx->expression( 1 ) );  // consequent
35 ✔
755
    addToken( ":", ctx->COLON(), FmtToken::SPACE | FmtToken::BREAKPOINT );
70 ✔
756

757
    visitExpression( ctx->expression( 2 ) );  // alternate
35 ✔
758
    return true;
35 ✔
759
  }
760

761
  return false;
×
762
}
763

764
antlrcpp::Any PrettifyFileProcessor::expression_suffix(
1,847 ✔
765
    EscriptParser::ExpressionContext* expr_ctx,
766
    EscriptParser::ExpressionSuffixContext* expr_suffix_ctx )
767
{
768
  if ( auto indexing = expr_suffix_ctx->indexingSuffix() )
1,847 ✔
769
  {
770
    visitExpression( expr_ctx );
510 ✔
771
    addToken( "[", indexing->LBRACK(), FmtToken::ATTACHED );
1,020 ✔
772
    visitIndexList( indexing->indexList() );
510 ✔
773
    addToken( "]", indexing->RBRACK(), FmtToken::SPACE | FmtToken::ATTACHED );
1,530 ✔
774
  }
775
  else if ( auto member = expr_suffix_ctx->navigationSuffix() )
1,337 ✔
776
  {
777
    visitExpression( expr_ctx );
363 ✔
778
    addToken( ".", member->DOT(), FmtToken::ATTACHED );
726 ✔
779
    if ( auto string_literal = member->STRING_LITERAL() )
363 ✔
780
      make_string_literal( string_literal );
1 ✔
781
    else if ( auto identifier = member->IDENTIFIER() )
362 ✔
782
      make_identifier( identifier );
354 ✔
783
    else if ( auto function_keyword = member->FUNCTION() )
8 ✔
784
      make_identifier( function_keyword );
8 ✔
785
  }
786
  else if ( auto method = expr_suffix_ctx->methodCallSuffix() )
974 ✔
787
  {
788
    visitExpression( expr_ctx );
888 ✔
789
    addToken( ".", method->DOT(), FmtToken::ATTACHED );
1,776 ✔
790
    make_identifier( method->IDENTIFIER() );
888 ✔
791
    addToken( "(", method->LPAREN(), linebuilder.openingParenthesisStyle() );
1,776 ✔
792
    bool args = false;
888 ✔
793
    if ( auto expr = method->expressionList() )
888 ✔
794
      args = std::any_cast<bool>( visitExpressionList( expr ) );
595 ✔
795
    addToken( ")", method->RPAREN(), linebuilder.closingParenthesisStyle( args ) );
2,664 ✔
796
  }
797
  else if ( auto function_call = expr_suffix_ctx->functionCallSuffix() )
86 ✔
798
  {
799
    visitExpression( expr_ctx );
86 ✔
800
    addToken( "(", function_call->LPAREN(), linebuilder.openingParenthesisStyle() );
172 ✔
801
    bool args = false;
86 ✔
802
    if ( auto expr = function_call->expressionList() )
86 ✔
803
      args = std::any_cast<bool>( visitExpressionList( expr ) );
76 ✔
804
    addToken( ")", function_call->RPAREN(), linebuilder.closingParenthesisStyle( args ) );
258 ✔
805
  }
806
  return {};
1,847 ✔
807
}
808

809
antlrcpp::Any PrettifyFileProcessor::visitFloatLiteral( EscriptParser::FloatLiteralContext* ctx )
577 ✔
810
{
811
  if ( auto float_literal = ctx->FLOAT_LITERAL() )
577 ✔
812
    return make_float_literal( float_literal );
574 ✔
813
  if ( auto hex_float_literal = ctx->HEX_FLOAT_LITERAL() )
3 ✔
814
    return make_float_literal( hex_float_literal );
3 ✔
815

816
  return visitChildren( ctx );
×
817
}
818

819
antlrcpp::Any PrettifyFileProcessor::visitForeachIterableExpression(
98 ✔
820
    EscriptParser::ForeachIterableExpressionContext* ctx )
821
{
822
  if ( auto parExpression = ctx->parExpression() )
98 ✔
823
  {
824
    visitParExpression( parExpression );
28 ✔
825
  }
826
  else if ( auto functionCall = ctx->functionCall() )
70 ✔
827
  {
828
    visitFunctionCall( functionCall );
15 ✔
829
  }
830
  else if ( auto scopedIdentifier = ctx->scopedIdentifier() )
55 ✔
831
  {
832
    visitScopedIdentifier( scopedIdentifier );
1 ✔
833
  }
834
  else if ( auto scopedFunctionCall = ctx->scopedFunctionCall() )
54 ✔
835
  {
836
    visitScopedFunctionCall( scopedFunctionCall );
1 ✔
837
  }
838
  else if ( auto identifier = ctx->IDENTIFIER() )
53 ✔
839
  {
840
    make_identifier( identifier );
45 ✔
841
  }
842
  else if ( auto explicitArrayInitializer = ctx->explicitArrayInitializer() )
8 ✔
843
  {
844
    visitExplicitArrayInitializer( explicitArrayInitializer );
3 ✔
845
  }
846
  else if ( auto bareArrayInitializer = ctx->bareArrayInitializer() )
5 ✔
847
  {
848
    visitBareArrayInitializer( bareArrayInitializer );
5 ✔
849
  }
850
  return {};
98 ✔
851
}
852

853
antlrcpp::Any PrettifyFileProcessor::visitForeachStatement(
98 ✔
854
    EscriptParser::ForeachStatementContext* ctx )
855
{
856
  make_statement_label( ctx->statementLabel() );
98 ✔
857
  addToken( "foreach", ctx->FOREACH(), FmtToken::SPACE );
196 ✔
858
  make_identifier( ctx->IDENTIFIER() );
98 ✔
859
  addToken( "in", ctx->TOK_IN(), FmtToken::SPACE );
196 ✔
860
  visitForeachIterableExpression( ctx->foreachIterableExpression() );
98 ✔
861
  linebuilder.buildLine( _currindent );
98 ✔
862

863
  visitBlock( ctx->block() );
98 ✔
864

865
  addToken( "endforeach", ctx->ENDFOREACH(), FmtToken::SPACE );
196 ✔
866
  linebuilder.buildLine( _currindent );
98 ✔
867
  return {};
98 ✔
868
}
869

870
antlrcpp::Any PrettifyFileProcessor::visitForStatement( EscriptParser::ForStatementContext* ctx )
36 ✔
871
{
872
  make_statement_label( ctx->statementLabel() );
36 ✔
873

874
  auto forGroup = ctx->forGroup();
36 ✔
875

876
  addToken( "for", ctx->FOR(), FmtToken::SPACE );
72 ✔
877
  if ( auto basicForStatement = forGroup->basicForStatement() )
36 ✔
878
    visitBasicForStatement( basicForStatement );
14 ✔
879
  else if ( auto cstyleForStatement = forGroup->cstyleForStatement() )
22 ✔
880
    visitCstyleForStatement( cstyleForStatement );
22 ✔
881
  addToken( "endfor", ctx->ENDFOR(), FmtToken::SPACE );
72 ✔
882
  linebuilder.buildLine( _currindent );
36 ✔
883
  return {};
36 ✔
884
}
885

886
antlrcpp::Any PrettifyFileProcessor::visitFunctionCall( EscriptParser::FunctionCallContext* ctx )
5,992 ✔
887
{
888
  make_identifier( ctx->IDENTIFIER() );
5,992 ✔
889
  _currentscope |= FmtToken::Scope::FUNCTION;
5,992 ✔
890

891
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle(),
11,984 ✔
892
            FmtContext::PREFERRED_BREAK_START );
893

894
  bool argcount = false;
5,992 ✔
895
  if ( auto args = ctx->expressionList() )
5,992 ✔
896
    argcount = std::any_cast<bool>( visitExpressionList( args ) );
5,745 ✔
897

898
  addToken( ")", ctx->RPAREN(), linebuilder.closingParenthesisStyle( argcount ),
11,984 ✔
899
            FmtContext::PREFERRED_BREAK_END );
900
  _currentscope &= ~FmtToken::Scope::FUNCTION;
5,992 ✔
901
  return {};
5,992 ✔
902
}
903
antlrcpp::Any PrettifyFileProcessor::visitFunctionDeclaration(
441 ✔
904
    EscriptParser::FunctionDeclarationContext* ctx )
905
{
906
  if ( auto exported = ctx->EXPORTED() )
441 ✔
907
    addToken( "exported", exported, FmtToken::SPACE );
6 ✔
908
  addToken( "function", ctx->FUNCTION(), FmtToken::SPACE );
882 ✔
909
  make_identifier( ctx->IDENTIFIER() );
441 ✔
910
  visitFunctionParameters( ctx->functionParameters() );
441 ✔
911

912
  visitBlock( ctx->block() );
441 ✔
913

914
  addToken( "endfunction", ctx->ENDFUNCTION(), FmtToken::SPACE );
882 ✔
915
  linebuilder.buildLine( _currindent );
441 ✔
916
  return {};
441 ✔
917
}
918

919
antlrcpp::Any PrettifyFileProcessor::visitFunctionParameters(
540 ✔
920
    EscriptParser::FunctionParametersContext* ctx )
921
{
922
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle(),
1,080 ✔
923
            FmtContext::PREFERRED_BREAK_START );
924

925
  bool argcount = false;
540 ✔
926
  if ( auto args = ctx->functionParameterList() )
540 ✔
927
    argcount = std::any_cast<bool>( visitFunctionParameterList( args ) );
446 ✔
928

929
  auto closingstyle = linebuilder.closingParenthesisStyle( argcount );
540 ✔
930
  if ( _suppressnewline )  // add space if newline is suppressed
540 ✔
931
    closingstyle |= FmtToken::SPACE;
99 ✔
932
  addToken( ")", ctx->RPAREN(), closingstyle, FmtContext::PREFERRED_BREAK_END );
1,080 ✔
933
  if ( !_suppressnewline )
540 ✔
934
    linebuilder.buildLine( _currindent );
441 ✔
935
  return {};
540 ✔
936
}
937

938
antlrcpp::Any PrettifyFileProcessor::visitFunctionParameterList(
446 ✔
939
    EscriptParser::FunctionParameterListContext* ctx )
940
{
941
  auto params = ctx->functionParameter();
446 ✔
942
  for ( size_t i = 0; i < params.size(); ++i )
1,209 ✔
943
  {
944
    visitFunctionParameter( params[i] );
763 ✔
945
    if ( i < params.size() - 1 )
763 ✔
946
      addToken( ",", ctx->COMMA( i ), linebuilder.delimiterStyle() | FmtToken::PREFERRED_BREAK );
951 ✔
947
  }
948
  return !params.empty();
892 ✔
949
}
446 ✔
950

951
antlrcpp::Any PrettifyFileProcessor::visitFunctionParameter(
763 ✔
952
    EscriptParser::FunctionParameterContext* ctx )
953
{
954
  if ( auto byref = ctx->BYREF() )
763 ✔
955
    addToken( "byref", byref, FmtToken::SPACE );
56 ✔
956
  if ( auto unused = ctx->UNUSED() )
763 ✔
957
    addToken( "unused", unused, FmtToken::SPACE );
42 ✔
958
  if ( auto default_keyword = ctx->DEFAULT() )
763 ✔
959
    addToken( "default", default_keyword, FmtToken::SPACE );
6 ✔
960
  make_identifier( ctx->IDENTIFIER() );
763 ✔
961

962
  if ( ctx->ELLIPSIS() )
763 ✔
963
    addToken( "...", ctx->ELLIPSIS(), linebuilder.ellipsisStyle() );
126 ✔
964

965
  if ( auto expression = ctx->expression() )
763 ✔
966
  {
967
    addToken( ":=", ctx->ASSIGN(), linebuilder.assignmentStyle() );
82 ✔
968
    visitExpression( expression );
41 ✔
969
  }
970
  return {};
763 ✔
971
}
972

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

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

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

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

1034
  addToken( ":", ctx->COLON(), FmtToken::SPACE | FmtToken::ATTACHED | FmtToken::BREAKPOINT );
186 ✔
1035
  linebuilder.markLastTokensAsSwitchLabel();
93 ✔
1036
  return {};
93 ✔
1037
}
1038

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

1060
antlrcpp::Any PrettifyFileProcessor::visitClassBody(
171 ✔
1061
    EscriptGrammar::EscriptParser::ClassBodyContext* ctx )
1062
{
1063
  ++_currindent;
171 ✔
1064
  visitChildren( ctx );
171 ✔
1065
  --_currindent;
171 ✔
1066
  return {};
171 ✔
1067
}
1068

1069
antlrcpp::Any PrettifyFileProcessor::visitClassDeclaration(
171 ✔
1070
    EscriptGrammar::EscriptParser::ClassDeclarationContext* ctx )
1071
{
1072
  addToken( "class", ctx->CLASS(), FmtToken::SPACE );
342 ✔
1073
  make_identifier( ctx->IDENTIFIER() );
171 ✔
1074
  visitClassParameters( ctx->classParameters() );
171 ✔
1075

1076
  visitClassBody( ctx->classBody() );
171 ✔
1077

1078
  addToken( "endclass", ctx->ENDCLASS(), FmtToken::SPACE );
342 ✔
1079
  linebuilder.buildLine( _currindent );
171 ✔
1080
  return {};
171 ✔
1081
}
1082

1083
antlrcpp::Any PrettifyFileProcessor::visitClassParameters(
171 ✔
1084
    EscriptGrammar::EscriptParser::ClassParametersContext* ctx )
1085
{
1086
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle(),
342 ✔
1087
            FmtContext::PREFERRED_BREAK_START );
1088

1089
  bool argcount = false;
171 ✔
1090
  if ( auto args = ctx->classParameterList() )
171 ✔
1091
    argcount = std::any_cast<bool>( visitClassParameterList( args ) );
73 ✔
1092

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

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

1113
  return !params.empty();
146 ✔
1114
}
73 ✔
1115

1116
antlrcpp::Any PrettifyFileProcessor::visitContinueStatement(
28 ✔
1117
    EscriptParser::ContinueStatementContext* ctx )
1118
{
1119
  addToken( "continue", ctx->CONTINUE(), FmtToken::SPACE );
56 ✔
1120

1121
  if ( auto identifier = ctx->IDENTIFIER() )
28 ✔
1122
    make_identifier( identifier );
5 ✔
1123

1124
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
56 ✔
1125
  linebuilder.buildLine( _currindent );
28 ✔
1126
  return {};
28 ✔
1127
}
1128

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

1139
  visitBlock( ctx->block() );
14 ✔
1140
  return {};
14 ✔
1141
}
1142

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

1155
  visitBlock( ctx->block() );
22 ✔
1156
  return {};
22 ✔
1157
}
1158

1159
antlrcpp::Any PrettifyFileProcessor::visitRepeatStatement(
15 ✔
1160
    EscriptParser::RepeatStatementContext* ctx )
1161
{
1162
  make_statement_label( ctx->statementLabel() );
15 ✔
1163
  addToken( "repeat", ctx->REPEAT(), FmtToken::SPACE );
30 ✔
1164
  linebuilder.buildLine( _currindent );
15 ✔
1165

1166
  visitBlock( ctx->block() );
15 ✔
1167

1168
  addToken( "until", ctx->UNTIL(), FmtToken::SPACE );
30 ✔
1169
  visitExpression( ctx->expression() );
15 ✔
1170
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
30 ✔
1171
  linebuilder.buildLine( _currindent );
15 ✔
1172
  return {};
15 ✔
1173
}
1174

1175
antlrcpp::Any PrettifyFileProcessor::visitReturnStatement(
221 ✔
1176
    EscriptParser::ReturnStatementContext* ctx )
1177
{
1178
  addToken( "return", ctx->RETURN(), FmtToken::SPACE );
442 ✔
1179
  if ( auto expression = ctx->expression() )
221 ✔
1180
    visitExpression( expression );
215 ✔
1181
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
442 ✔
1182
  linebuilder.buildLine( _currindent );
221 ✔
1183
  return {};
221 ✔
1184
}
1185

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

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

1212
antlrcpp::Any PrettifyFileProcessor::visitFunctionReference(
231 ✔
1213
    EscriptParser::FunctionReferenceContext* ctx )
1214
{
1215
  addToken( "@", ctx->AT(), FmtToken::NONE );
462 ✔
1216

1217
  if ( ctx->scope )
231 ✔
1218
  {
1219
    addToken( ctx->scope->getText(), ctx->scope, FmtToken::NONE );
14 ✔
1220
    addToken( "::", ctx->COLONCOLON(), FmtToken::ATTACHED );
42 ✔
1221
  }
1222

1223
  addToken( ctx->function->getText(), ctx->function, FmtToken::SPACE );
231 ✔
1224
  return {};
231 ✔
1225
}
1226

1227
antlrcpp::Any PrettifyFileProcessor::visitFunctionExpression(
96 ✔
1228
    EscriptGrammar::EscriptParser::FunctionExpressionContext* ctx )
1229
{
1230
  addToken( "@", ctx->AT(), FmtToken::NONE );
192 ✔
1231

1232

1233
  _suppressnewline = true;  // functionparams force newline
96 ✔
1234
  if ( auto params = ctx->functionParameters() )
96 ✔
1235
    visitFunctionParameters( params );
84 ✔
1236
  _suppressnewline = false;
96 ✔
1237

1238
  // we want the starting { at the same line and not attached
1239
  addToken( "{", ctx->LBRACE(), linebuilder.openingBracketStyle() & ~FmtToken::ATTACHED );
192 ✔
1240
  if ( compilercfg.FormatterAllowShortFuncRefsOnASingleLine )
96 ✔
1241
    linebuilder.markPackableLineStart();
96 ✔
1242
  linebuilder.buildLine( _currindent );  // now start a newline
96 ✔
1243

1244
  ++_currentgroup;
96 ✔
1245
  size_t curcount = linebuilder.currentTokens().size();
96 ✔
1246
  visitBlock( ctx->block() );
96 ✔
1247
  --_currentgroup;
96 ✔
1248

1249
  addToken( "}", ctx->RBRACE(), linebuilder.closingBracketStyle( curcount ) );
192 ✔
1250
  if ( compilercfg.FormatterAllowShortFuncRefsOnASingleLine )
96 ✔
1251
    linebuilder.markPackableLineEnd();
96 ✔
1252
  return {};
96 ✔
1253
}
1254

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

1264
antlrcpp::Any PrettifyFileProcessor::visitIfStatement( EscriptParser::IfStatementContext* ctx )
326 ✔
1265
{
1266
  auto blocks = ctx->block();
326 ✔
1267
  auto par_expression = ctx->parExpression();
326 ✔
1268
  size_t num_expressions = par_expression.size();
326 ✔
1269
  for ( size_t clause_index = 0; clause_index < num_expressions; ++clause_index )
678 ✔
1270
  {
1271
    auto expression_ctx = par_expression.at( clause_index );
352 ✔
1272
    if ( !clause_index )
352 ✔
1273
      addToken( "if", ctx->IF(), FmtToken::SPACE );
978 ✔
1274
    else
1275
      addToken( "elseif", ctx->ELSEIF( clause_index - 1 ), FmtToken::SPACE );
78 ✔
1276
    auto expression_ast = visitParExpression( expression_ctx );
352 ✔
1277
    if ( !clause_index && ctx->THEN() )
352 ✔
1278
      addToken( "then", ctx->THEN(), FmtToken::SPACE );
3 ✔
1279

1280
    linebuilder.buildLine( _currindent );
352 ✔
1281

1282
    if ( blocks.size() > clause_index )
352 ✔
1283
      visitBlock( blocks.at( clause_index ) );
352 ✔
1284
  }
352 ✔
1285
  if ( ctx->ELSE() )
326 ✔
1286
  {
1287
    addToken( "else", ctx->ELSE(), FmtToken::SPACE );
298 ✔
1288
    linebuilder.buildLine( _currindent );
149 ✔
1289
    visitBlock( blocks.at( blocks.size() - 1 ) );
149 ✔
1290
  }
1291
  addToken( "endif", ctx->ENDIF(), FmtToken::SPACE );
652 ✔
1292
  linebuilder.buildLine( _currindent );
326 ✔
1293
  return {};
652 ✔
1294
}
326 ✔
1295

1296
antlrcpp::Any PrettifyFileProcessor::visitIncludeDeclaration(
56 ✔
1297
    EscriptParser::IncludeDeclarationContext* ctx )
1298
{
1299
  addToken( "include", ctx->INCLUDE(), FmtToken::SPACE );
112 ✔
1300
  visitStringIdentifier( ctx->stringIdentifier() );
56 ✔
1301
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
112 ✔
1302
  linebuilder.buildLine( _currindent );
56 ✔
1303
  return {};
56 ✔
1304
}
1305

1306
antlrcpp::Any PrettifyFileProcessor::visitInterpolatedString(
312 ✔
1307
    EscriptParser::InterpolatedStringContext* ctx )
1308
{
1309
  addToken( "$\"", ctx->INTERPOLATED_STRING_START(), FmtToken::SPACE );
624 ✔
1310
  visitChildren( ctx );
312 ✔
1311
  addToken( "\"", ctx->DOUBLE_QUOTE_INSIDE(), FmtToken::ATTACHED | FmtToken::SPACE );
624 ✔
1312
  return {};
312 ✔
1313
}
1314

1315
antlrcpp::Any PrettifyFileProcessor::visitInterpolatedStringPart(
974 ✔
1316
    EscriptParser::InterpolatedStringPartContext* ctx )
1317
{
1318
  if ( auto expression_ctx = ctx->expression() )
974 ✔
1319
  {
1320
    addToken( "{", ctx->LBRACE_INSIDE(), FmtToken::ATTACHED );
972 ✔
1321
    visitExpression( expression_ctx );
486 ✔
1322

1323
    if ( auto format_string = ctx->FORMAT_STRING() )
486 ✔
1324
    {
1325
      addToken( ":", ctx->COLON(), FmtToken::ATTACHED );
48 ✔
1326
      addToken( format_string->getText(), format_string, FmtToken::ATTACHED );
24 ✔
1327
    }
1328
    // TODO: this seems to be the only non token
1329
    Range r( *expression_ctx );
486 ✔
1330
    addToken( "}", r.end, FmtToken::ATTACHED, 0 );
972 ✔
1331
  }
1332

1333
  else if ( auto string_literal = ctx->STRING_LITERAL_INSIDE() )
488 ✔
1334
  {
1335
    addToken( string_literal->getText(), string_literal, FmtToken::ATTACHED );
459 ✔
1336
  }
1337
  else if ( auto lbrace = ctx->DOUBLE_LBRACE_INSIDE() )
29 ✔
1338
  {
1339
    addToken( "{{", lbrace, FmtToken::ATTACHED );
28 ✔
1340
  }
1341
  else if ( auto rbrace = ctx->DOUBLE_RBRACE() )
15 ✔
1342
  {
1343
    addToken( "}}", rbrace, FmtToken::ATTACHED );
24 ✔
1344
  }
1345
  else if ( auto escaped = ctx->REGULAR_CHAR_INSIDE() )
3 ✔
1346
  {
1347
    addToken( escaped->getText(), escaped, FmtToken::ATTACHED );
3 ✔
1348
  }
1349
  return {};
974 ✔
1350
}
1351

1352
antlrcpp::Any PrettifyFileProcessor::visitBoolLiteral( EscriptParser::BoolLiteralContext* ctx )
868 ✔
1353
{
1354
  if ( auto bool_false = ctx->BOOL_FALSE() )
868 ✔
1355
    make_bool_literal( bool_false );
228 ✔
1356
  else if ( auto bool_true = ctx->BOOL_TRUE() )
640 ✔
1357
    make_bool_literal( bool_true );
640 ✔
1358
  return {};
868 ✔
1359
}
1360

1361
antlrcpp::Any PrettifyFileProcessor::visitIntegerLiteral(
3,536 ✔
1362
    EscriptParser::IntegerLiteralContext* ctx )
1363
{
1364
  if ( auto decimal_literal = ctx->DECIMAL_LITERAL() )
3,536 ✔
1365
    return make_integer_literal( decimal_literal );
3,492 ✔
1366

1367
  if ( auto hex_literal = ctx->HEX_LITERAL() )
44 ✔
1368
    return make_integer_literal( hex_literal );
41 ✔
1369

1370
  if ( auto oct_literal = ctx->OCT_LITERAL() )
3 ✔
1371
    return make_integer_literal( oct_literal );
3 ✔
1372

1373
  if ( auto binary_literal = ctx->BINARY_LITERAL() )
×
1374
    return make_integer_literal( binary_literal );
×
1375

1376
  return visitChildren( ctx );
×
1377
}
1378

1379
antlrcpp::Any PrettifyFileProcessor::visitLiteral( EscriptParser::LiteralContext* ctx )
10,003 ✔
1380
{
1381
  if ( auto string_literal = ctx->STRING_LITERAL() )
10,003 ✔
1382
    return make_string_literal( string_literal );
4,968 ✔
1383
  if ( auto integer_literal = ctx->integerLiteral() )
5,035 ✔
1384
    return visitIntegerLiteral( integer_literal );
3,506 ✔
1385
  if ( auto float_literal = ctx->floatLiteral() )
1,529 ✔
1386
    return visitFloatLiteral( float_literal );
577 ✔
1387
  if ( auto uninit = ctx->UNINIT() )
952 ✔
1388
    addToken( "uninit", uninit, FmtToken::SPACE );
76 ✔
1389
  if ( auto bool_literal = ctx->boolLiteral() )
952 ✔
1390
    return visitBoolLiteral( bool_literal );
864 ✔
1391
  if ( auto regular_expression_literal = ctx->REGEXP_LITERAL() )
88 ✔
1392
    return make_regular_expression_literal( regular_expression_literal );
50 ✔
1393
  return visitChildren( ctx );
38 ✔
1394
}
1395

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

1405
  addToken( ")", ctx->RPAREN(), linebuilder.closingParenthesisStyle( args ) );
×
1406
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
×
1407
  linebuilder.buildLine( _currindent );
×
1408
  return {};
×
1409
}
1410

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

1424
antlrcpp::Any PrettifyFileProcessor::visitModuleFunctionParameter(
×
1425
    EscriptParser::ModuleFunctionParameterContext* ctx )
1426
{
1427
  make_identifier( ctx->IDENTIFIER() );
×
1428

1429
  if ( auto expression = ctx->expression() )
×
1430
  {
1431
    addToken( ":=", ctx->ASSIGN(), linebuilder.assignmentStyle() );
×
1432
    visitExpression( expression );
×
1433
  }
1434
  return {};
×
1435
}
1436

1437
antlrcpp::Any PrettifyFileProcessor::visitPrimary( EscriptParser::PrimaryContext* ctx )
25,060 ✔
1438
{
1439
  if ( auto literal = ctx->literal() )
25,060 ✔
1440
    return visitLiteral( literal );
10,003 ✔
1441
  if ( auto parExpression = ctx->parExpression() )
15,057 ✔
1442
    return visitParExpression( parExpression );
287 ✔
1443
  if ( auto functionCall = ctx->functionCall() )
14,770 ✔
1444
    return visitFunctionCall( functionCall );
5,919 ✔
1445
  if ( auto scopedIdentifier = ctx->scopedIdentifier() )
8,851 ✔
1446
    return visitScopedIdentifier( scopedIdentifier );
53 ✔
1447
  if ( auto scopedFunctionCall = ctx->scopedFunctionCall() )
8,798 ✔
1448
    return visitScopedFunctionCall( scopedFunctionCall );
57 ✔
1449
  if ( auto identifier = ctx->IDENTIFIER() )
8,741 ✔
1450
    return make_identifier( identifier );
7,526 ✔
1451
  if ( auto functionReference = ctx->functionReference() )
1,215 ✔
1452
    return visitFunctionReference( functionReference );
231 ✔
1453
  if ( auto functionExpression = ctx->functionExpression() )
984 ✔
1454
    return visitFunctionExpression( functionExpression );
96 ✔
1455
  if ( auto explicitArrayInitializer = ctx->explicitArrayInitializer() )
888 ✔
1456
    return visitExplicitArrayInitializer( explicitArrayInitializer );
163 ✔
1457
  if ( auto explicitStructInitializer = ctx->explicitStructInitializer() )
725 ✔
1458
    return visitExplicitStructInitializer( explicitStructInitializer );
125 ✔
1459
  if ( auto explicitDictInitializer = ctx->explicitDictInitializer() )
600 ✔
1460
    return visitExplicitDictInitializer( explicitDictInitializer );
65 ✔
1461
  if ( auto explicitErrorInitializer = ctx->explicitErrorInitializer() )
535 ✔
1462
    return visitExplicitErrorInitializer( explicitErrorInitializer );
19 ✔
1463
  if ( auto bareArrayInitializer = ctx->bareArrayInitializer() )
516 ✔
1464
    return visitBareArrayInitializer( bareArrayInitializer );
204 ✔
1465
  if ( auto interpolatedString = ctx->interpolatedString() )
312 ✔
1466
    return visitInterpolatedString( interpolatedString );
312 ✔
1467
  return {};
×
1468
}
1469

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

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

1497
antlrcpp::Any PrettifyFileProcessor::visitProgramParameters(
91 ✔
1498
    EscriptParser::ProgramParametersContext* ctx )
1499
{
1500
  addToken( "(", ctx->LPAREN(), linebuilder.openingParenthesisStyle() );
182 ✔
1501

1502
  bool args = false;
91 ✔
1503
  if ( auto programParameterList = ctx->programParameterList() )
91 ✔
1504
    args = std::any_cast<bool>( visitProgramParameterList( programParameterList ) );
12 ✔
1505

1506
  addToken( ")", ctx->RPAREN(), linebuilder.closingParenthesisStyle( args ) );
182 ✔
1507
  return {};
91 ✔
1508
}
1509

1510
antlrcpp::Any PrettifyFileProcessor::visitProgramParameter(
14 ✔
1511
    EscriptParser::ProgramParameterContext* ctx )
1512
{
1513
  if ( auto unused = ctx->UNUSED() )
14 ✔
1514
    addToken( "unused", unused, FmtToken::SPACE );
4 ✔
1515

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

1525
antlrcpp::Any PrettifyFileProcessor::visitStatement( EscriptParser::StatementContext* ctx )
8,808 ✔
1526
{
1527
  if ( auto ifStatement = ctx->ifStatement() )
8,808 ✔
1528
    return visitIfStatement( ifStatement );
326 ✔
1529
  if ( auto gotoStatement = ctx->gotoStatement() )
8,482 ✔
1530
    return visitGotoStatement( gotoStatement );
×
1531
  if ( auto returnStatement = ctx->returnStatement() )
8,482 ✔
1532
    return visitReturnStatement( returnStatement );
221 ✔
1533
  if ( auto constStatement = ctx->constStatement() )
8,261 ✔
1534
    return visitConstStatement( constStatement );
77 ✔
1535
  if ( auto varStatement = ctx->varStatement() )
8,184 ✔
1536
    return visitVarStatement( varStatement );
1,091 ✔
1537
  if ( auto doStatement = ctx->doStatement() )
7,093 ✔
1538
    return visitDoStatement( doStatement );
7 ✔
1539
  if ( auto whileStatement = ctx->whileStatement() )
7,086 ✔
1540
    return visitWhileStatement( whileStatement );
45 ✔
1541
  if ( auto exitStatement = ctx->exitStatement() )
7,041 ✔
1542
    return visitExitStatement( exitStatement );
6 ✔
1543
  if ( auto breakStatement = ctx->breakStatement() )
7,035 ✔
1544
    return visitBreakStatement( breakStatement );
44 ✔
1545
  if ( auto continueStatement = ctx->continueStatement() )
6,991 ✔
1546
    return visitContinueStatement( continueStatement );
28 ✔
1547
  if ( auto forStatement = ctx->forStatement() )
6,963 ✔
1548
    return visitForStatement( forStatement );
36 ✔
1549
  if ( auto foreachStatement = ctx->foreachStatement() )
6,927 ✔
1550
    return visitForeachStatement( foreachStatement );
98 ✔
1551
  if ( auto repeatStatement = ctx->repeatStatement() )
6,829 ✔
1552
    return visitRepeatStatement( repeatStatement );
15 ✔
1553
  if ( auto caseStatement = ctx->caseStatement() )
6,814 ✔
1554
    return visitCaseStatement( caseStatement );
28 ✔
1555
  if ( auto enumStatement = ctx->enumStatement() )
6,786 ✔
1556
    return visitEnumStatement( enumStatement );
13 ✔
1557
  if ( auto expression = ctx->statementExpression )
6,773 ✔
1558
  {
1559
    visitExpression( expression );
6,773 ✔
1560

1561
    addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
13,546 ✔
1562
    _currentscope &= ~FmtToken::Scope::VAR;  // matches with assignment inside of visitExpression
6,773 ✔
1563
    linebuilder.buildLine( _currindent );
6,773 ✔
1564
    return {};
6,773 ✔
1565
  }
1566

1567
  return {};
×
1568
}
1569

1570
antlrcpp::Any PrettifyFileProcessor::visitStringIdentifier(
100 ✔
1571
    EscriptParser::StringIdentifierContext* ctx )
1572
{
1573
  if ( auto identifier = ctx->IDENTIFIER() )
100 ✔
1574
    return make_identifier( identifier );
46 ✔
1575
  if ( auto string_literal = ctx->STRING_LITERAL() )
54 ✔
1576
    return make_string_literal( string_literal );
54 ✔
1577
  return {};
×
1578
}
1579

1580
antlrcpp::Any PrettifyFileProcessor::visitStructInitializerExpression(
197 ✔
1581
    EscriptParser::StructInitializerExpressionContext* ctx )
1582
{
1583
  if ( auto identifier = ctx->IDENTIFIER() )
197 ✔
1584
    make_identifier( identifier );
187 ✔
1585
  else if ( auto string_literal = ctx->STRING_LITERAL() )
10 ✔
1586
    make_string_literal( string_literal );
7 ✔
1587

1588
  if ( auto expression = ctx->expression() )
197 ✔
1589
  {
1590
    if ( auto assign = ctx->ASSIGN() )
181 ✔
1591
      addToken( ":=", assign, linebuilder.assignmentStyle() );
534 ✔
1592

1593
    visitExpression( expression );
181 ✔
1594

1595
    if ( ctx->ELLIPSIS() )
181 ✔
1596
    {
1597
      addToken( "...", ctx->ELLIPSIS(), linebuilder.ellipsisStyle() );
9 ✔
1598
    }
1599
  }
1600

1601
  return {};
197 ✔
1602
}
1603

1604
antlrcpp::Any PrettifyFileProcessor::visitUseDeclaration(
44 ✔
1605
    EscriptParser::UseDeclarationContext* ctx )
1606
{
1607
  addToken( "use", ctx->USE(), FmtToken::SPACE );
88 ✔
1608
  visitStringIdentifier( ctx->stringIdentifier() );
44 ✔
1609
  addToken( ";", ctx->SEMI(), linebuilder.terminatorStyle() );
88 ✔
1610

1611
  linebuilder.buildLine( _currindent );
44 ✔
1612
  return {};
44 ✔
1613
}
1614

1615
antlrcpp::Any PrettifyFileProcessor::make_statement_label(
229 ✔
1616
    EscriptParser::StatementLabelContext* ctx )
1617
{
1618
  if ( ctx )
229 ✔
1619
  {
1620
    make_identifier( ctx->IDENTIFIER() );
14 ✔
1621
    addToken( ":", ctx->COLON(), FmtToken::SPACE | FmtToken::ATTACHED );
42 ✔
1622
  }
1623
  return {};
229 ✔
1624
}
1625

1626
antlrcpp::Any PrettifyFileProcessor::make_identifier( antlr4::tree::TerminalNode* terminal )
18,289 ✔
1627
{
1628
  addToken( terminal->getText(), terminal, FmtToken::SPACE );
18,289 ✔
1629
  return {};
18,289 ✔
1630
}
1631

1632
antlrcpp::Any PrettifyFileProcessor::make_string_literal( antlr4::tree::TerminalNode* terminal )
5,051 ✔
1633
{
1634
  addToken( terminal->getText(), terminal, FmtToken::SPACE );
5,051 ✔
1635
  return {};
5,051 ✔
1636
}
1637

1638
antlrcpp::Any PrettifyFileProcessor::make_integer_literal( antlr4::tree::TerminalNode* terminal )
3,536 ✔
1639
{
1640
  addToken( terminal->getText(), terminal, FmtToken::SPACE );
3,536 ✔
1641
  return {};
3,536 ✔
1642
}
1643

1644
antlrcpp::Any PrettifyFileProcessor::make_float_literal( antlr4::tree::TerminalNode* terminal )
577 ✔
1645
{
1646
  addToken( terminal->getText(), terminal, FmtToken::SPACE );
577 ✔
1647
  return {};
577 ✔
1648
}
1649

1650
antlrcpp::Any PrettifyFileProcessor::make_bool_literal( antlr4::tree::TerminalNode* terminal )
868 ✔
1651
{
1652
  addToken( terminal->getText(), terminal, FmtToken::SPACE );
868 ✔
1653
  return {};
868 ✔
1654
}
1655

1656
antlrcpp::Any PrettifyFileProcessor::make_regular_expression_literal(
50 ✔
1657
    antlr4::tree::TerminalNode* terminal )
1658
{
1659
  addToken( terminal->getText(), terminal, FmtToken::SPACE );
50 ✔
1660
  return {};
50 ✔
1661
}
1662

1663
void PrettifyFileProcessor::addToken( std::string&& text, const Position& pos, int style,
76,299 ✔
1664
                                      size_t token_type, FmtContext context )
1665
{
1666
  linebuilder.addPart( { std::forward<std::string>( text ), pos, style, _currentgroup, token_type,
76,299 ✔
1667
                         context, _currentscope } );
1668
}
76,299 ✔
1669
void PrettifyFileProcessor::addToken( std::string&& text, antlr4::tree::TerminalNode* terminal,
70,146 ✔
1670
                                      int style, FmtContext context )
1671
{
1672
  if ( compilercfg.FormatterKeepKeywords )
70,146 ✔
1673
    addToken( terminal->getSymbol()->getText(), Range( *terminal ).start, style,
×
1674
              terminal->getSymbol()->getType(), context );
×
1675
  else
1676
    addToken( std::forward<std::string>( text ), Range( *terminal ).start, style,
70,146 ✔
1677
              terminal->getSymbol()->getType(), context );
70,146 ✔
1678
}
70,146 ✔
1679
void PrettifyFileProcessor::addToken( std::string&& text, antlr4::Token* token, int style,
5,667 ✔
1680
                                      FmtContext context )
1681
{
1682
  if ( compilercfg.FormatterKeepKeywords )
5,667 ✔
1683
    addToken( token->getText(), Range( token ).start, style, token->getType(), context );
×
1684
  else
1685
    addToken( std::forward<std::string>( text ), Range( token ).start, style, token->getType(),
5,667 ✔
1686
              context );
1687
}
5,667 ✔
1688

1689
void PrettifyFileProcessor::preprocess( SourceFile& sf, std::optional<Range> format_range )
710 ✔
1690
{
1691
  auto rawlines = load_raw_file();
710 ✔
1692
  auto comments = collectComments( sf );
710 ✔
NEW
1693
  auto column_for_line = [&]( size_t line /* 1-based */ )
×
1694
  {
NEW
1695
    if ( line <= rawlines.size() )
×
1696
    {
NEW
1697
      return rawlines[line - 1].length() + 1;
×
1698
    }
NEW
1699
    return std::numeric_limits<size_t>::max();
×
1700
  };
710 ✔
1701

1702
  std::vector<Range> skiplines;
710 ✔
1703

1704
  // The skipline range corresponding to _before_ the format range.
1705
  std::optional<Range> format_range_skip_head;
710 ✔
1706

1707
  // The skipline range correspond to _after_ the format range.
1708
  std::optional<Range> format_range_skip_foot;
710 ✔
1709

1710
  if ( format_range.has_value() )
710 ✔
1711
  {
1712
    // Only create skipline head if format range starts after first line.
NEW
1713
    if ( format_range->start.line_number > 1 )
×
1714
    {
1715
      format_range_skip_head =
NEW
1716
          Range( Position{ 1, 1, 0 },
×
NEW
1717
                 Position{ format_range->start.line_number - 1,
×
NEW
1718
                           column_for_line( format_range->start.line_number - 1 ), 0 } );
×
1719
    }
1720

1721
    // Only create skipline foot if format range ends before last line.
NEW
1722
    if ( format_range->end.line_number < rawlines.size() )
×
1723
    {
1724
      format_range_skip_foot =
NEW
1725
          Range( Position{ format_range->end.line_number + 1, 1, 0 },
×
NEW
1726
                 Position{ rawlines.size(), column_for_line( rawlines.size() ), 0 } );
×
1727
    }
1728
  }
1729

1730
  for ( const auto& c : comments )
2,027 ✔
1731
  {
1732
    if ( c.text.find( "format-off" ) != std::string::npos )
1,317 ✔
1733
      skiplines.emplace_back( c.pos, c.pos );
6 ✔
1734
    else if ( c.text.find( "format-on" ) != std::string::npos )
1,311 ✔
1735
      if ( !skiplines.empty() )
×
1736
        skiplines.back().end = c.pos_end;
×
1737
  }
1738
  if ( !skiplines.empty() )
710 ✔
1739
  {
1740
    // set unmatched end to file eof
1741
    if ( skiplines.back().start.line_number == skiplines.back().end.line_number )
6 ✔
1742
      skiplines.back().end.line_number = rawlines.size() + 1;
6 ✔
1743

1744
    bool skipAll = false;
6 ✔
1745

1746
    // Case 1: `format_range` is completely inside a skipline.
1747
    // If so, do not format anything, ie. have only one skipline covering the entire file.
1748
    if ( format_range.has_value() )
6 ✔
NEW
1749
      skipAll = std::ranges::any_of(
×
NEW
1750
          skiplines, [&]( const auto& skipline ) { return skipline.contains( *format_range ); } );
×
1751

1752
    if ( skipAll )
6 ✔
1753
    {
1754
      // Replace all skiplines with one skipline covering the entire file.
NEW
1755
      format_range_skip_head = {};
×
NEW
1756
      format_range_skip_foot = {};
×
NEW
1757
      skiplines.clear();
×
1758
      // skiplines.emplace_back( Position{ 1, 1, 0 },
1759
      //                         Position{ rawlines.size(), column_for_line( rawlines.size() ), 0 }
1760
      //                         );
NEW
1761
      skiplines.emplace_back( Position{ 1, 0, 0 },
×
NEW
1762
                              Position{ rawlines.size(), column_for_line( rawlines.size() ), 0 } );
×
1763
    }
1764
    else
1765
    {
1766
      if ( format_range_skip_head.has_value() )
6 ✔
1767
      {
NEW
1768
        for ( auto itr = skiplines.begin(); itr < skiplines.end(); )
×
1769
        {
NEW
1770
          auto& skipline = *itr;
×
1771

1772
          // Case 2: Skipline is partially contained inside head.
1773
          // If so, extend head to end of skipline and remove skipline
NEW
1774
          if ( format_range_skip_head->contains( skipline.start ) &&
×
NEW
1775
               !format_range_skip_head->contains( skipline.end ) )
×
1776
          {
NEW
1777
            format_range_skip_head->end.line_number = skipline.end.line_number;
×
NEW
1778
            itr = skiplines.erase( itr );
×
1779
          }
1780
          // Case 3: Skipline is completely contained inside head.
1781
          // If so, remove skipline, as it will not be formatted anyway because of head's range.
NEW
1782
          else if ( format_range_skip_head->contains( skipline ) )
×
1783
          {
NEW
1784
            itr = skiplines.erase( itr );
×
1785
          }
1786
          // Case 4: Skipline exists inside formatting range.
1787
          // If so, keep skipline as-is, and formatter will skip this range.
1788
          else
1789
          {
NEW
1790
            ++itr;
×
1791
          }
1792
        }
1793
      }
1794

1795
      if ( format_range_skip_foot.has_value() )
6 ✔
1796
      {
NEW
1797
        for ( auto itr = skiplines.begin(); itr < skiplines.end(); )
×
1798
        {
NEW
1799
          auto& skipline = *itr;
×
1800

1801
          // Case 5: Skipline is partially contained inside foot.
1802
          // If so, extend foot to start of skipline and remove skipline
NEW
1803
          if ( format_range_skip_foot->contains( skipline.end ) &&
×
NEW
1804
               !format_range_skip_foot->contains( skipline.start ) )
×
1805
          {
NEW
1806
            format_range_skip_foot->start.line_number = skipline.start.line_number;
×
NEW
1807
            itr = skiplines.erase( itr );
×
1808
          }
1809
          // Case 6: Skipline is completely contained inside foot.
1810
          // If so, remove skipline, as it will not be formatted anyway because of foot's range.
NEW
1811
          else if ( format_range_skip_foot->contains( skipline ) )
×
1812
          {
NEW
1813
            itr = skiplines.erase( itr );
×
1814
          }
1815
          // Case 4: Skipline exists inside formatting range.
1816
          // If so, keep skipline as-is, and formatter will skip this range.
1817
          else
1818
          {
NEW
1819
            ++itr;
×
1820
          }
1821
        }
1822
      }
1823
    }
1824
  }
1825

1826
  // If head exists, add to start of vector.
1827
  if ( format_range_skip_head.has_value() )
710 ✔
1828
  {
NEW
1829
    skiplines.insert( skiplines.begin(), format_range_skip_head.value() );
×
1830
  }
1831

1832
  // If foot exists, add to end of vector.
1833
  if ( format_range_skip_foot.has_value() )
710 ✔
1834
  {
NEW
1835
    skiplines.push_back( format_range_skip_foot.value() );
×
1836
  }
1837

1838
  // remove all comments between noformat ranges
1839
  comments.erase( std::remove_if( comments.begin(), comments.end(),
710 ✔
1840
                                  [&]( auto& c )
1,317 ✔
1841
                                  {
1842
                                    for ( const auto& s : skiplines )
1,321 ✔
1843
                                    {
1844
                                      if ( s.start.line_number <= c.pos.line_number &&
36 ✔
1845
                                           s.end.line_number >= c.pos.line_number )
32 ✔
1846
                                        return true;
32 ✔
1847
                                    }
1848
                                    return false;
1,285 ✔
1849
                                  } ),
1850
                  comments.end() );
710 ✔
1851
  linebuilder.setComments( std::move( comments ) );
710 ✔
1852
  linebuilder.setSkipLines( std::move( skiplines ), format_range.has_value() );
710 ✔
1853
  linebuilder.setRawLines( std::move( rawlines ) );
710 ✔
1854
}
710 ✔
1855

1856
std::vector<std::string> PrettifyFileProcessor::load_raw_file()
710 ✔
1857
{
1858
  // Clib::FileContents fc( source_file_identifier.pathname.c_str(), true );
1859
  // const auto& contents = fc.str_contents();
1860
  const auto contents = source_loader.get_contents( source_file_identifier.pathname );
710 ✔
1861
  std::vector<std::string> rawlines;
710 ✔
1862
  std::string currline;
710 ✔
1863
  for ( size_t i = 0; i < contents.size(); ++i )
347,946 ✔
1864
  {
1865
    if ( contents[i] == '\r' && i + 1 < contents.size() && contents[i + 1] == '\n' )
347,236 ✔
1866
    {
1867
      ++i;
×
1868
      rawlines.emplace_back( std::move( currline ) );
×
1869
      currline.clear();
×
1870
      continue;
×
1871
    }
1872
    if ( contents[i] == '\r' || contents[i] == '\n' )
347,236 ✔
1873
    {
1874
      rawlines.emplace_back( std::move( currline ) );
14,386 ✔
1875
      currline.clear();
14,386 ✔
1876
    }
1877
    else
1878
      currline += contents[i];
332,850 ✔
1879
  }
1880
  if ( !currline.empty() )
710 ✔
1881
    rawlines.emplace_back( std::move( currline ) );
1 ✔
1882
  return rawlines;
710 ✔
1883
}
710 ✔
1884

1885
std::vector<FmtToken> PrettifyFileProcessor::collectComments( SourceFile& sf )
710 ✔
1886
{
1887
  auto alltokens = sf.get_all_tokens();
710 ✔
1888
  std::vector<FmtToken> comments;
710 ✔
1889
  for ( size_t i = 0; i < alltokens.size(); ++i )
127,543 ✔
1890
  {
1891
    const auto& comment = alltokens[i];
126,833 ✔
1892
    if ( comment->getType() == EscriptLexer::COMMENT ||
253,632 ✔
1893
         comment->getType() == EscriptLexer::LINE_COMMENT )
126,799 ✔
1894
    {
1895
      Range startpos( comment );
1,317 ✔
1896
      Range endpos( comment );
1,317 ✔
1897

1898
      // use whitespace token as start if its on the same line
1899
      // so that the tokenid of a comment is always the next tokenid after a "actual" token
1900
      if ( i > 0 )
1,317 ✔
1901
      {
1902
        if ( alltokens[i - 1]->getType() == EscriptLexer::WS &&
2,290 ✔
1903
             alltokens[i - 1]->getLine() == startpos.start.line_number )
1,145 ✔
1904
          startpos = Range( alltokens[i - 1] );
331 ✔
1905
      }
1906
      FmtToken info;
1,317 ✔
1907
      info.text = comment->getText();
1,317 ✔
1908
      info.token_type = comment->getType();
1,317 ✔
1909
      info.style = FmtToken::SPACE;
1,317 ✔
1910
      // replace tabs with spaces if not active
1911
      if ( compilercfg.FormatterFormatInsideComments && !compilercfg.FormatterUseTabs )
1,317 ✔
1912
      {
1913
        auto it = info.text.find( '\t' );
1,317 ✔
1914
        while ( it != std::string::npos )
1,317 ✔
1915
        {
1916
          // replacing tabs inbetween is a bit more complicated...
1917
          // the size is based on the next tabstop which is eg 4
1918
          // if its multiline we need to calc it based on the last newline
1919
          auto lastnewline = info.text.find_last_of( '\n', it );
×
1920
          if ( lastnewline == std::string::npos )
×
1921
            lastnewline = 0;
×
1922
          auto delta = ( it - lastnewline ) % compilercfg.FormatterTabWidth;
×
1923
          info.text.replace( it, 1, std::string( compilercfg.FormatterTabWidth - delta, ' ' ) );
×
1924
          it = info.text.find( '\t' );
×
1925
        }
1926
      }
1927
      if ( info.token_type == EscriptLexer::LINE_COMMENT )
1,317 ✔
1928
      {
1929
        info.context = FmtContext::LINE_COMMENT;
1,283 ✔
1930
        info.style |= FmtToken::FORCED_BREAK;
1,283 ✔
1931
        if ( compilercfg.FormatterFormatInsideComments )
1,283 ✔
1932
        {
1933
          info.text.erase( 0, 2 );  // remove //
1,283 ✔
1934
          auto firstchar = info.text.find_first_not_of( " \t" );
1,283 ✔
1935
          if ( info.text.empty() || firstchar == std::string::npos )
1,283 ✔
1936
          {
1937
            // empty or only whitespace
1938
            info.text = "//";
51 ✔
1939
          }
1940
          else if ( info.text.front() == '/' )
1,232 ✔
1941
          {
1942
            // assuming its ////// -> keep it
1943
            info.text = std::string( "//" ) + info.text;
8 ✔
1944
          }
1945
          else
1946
          {
1947
            // add space if non is there
1948
            if ( info.text.front() != ' ' )
1,228 ✔
1949
              info.text = std::string( "// " ) + info.text;
×
1950
            else
1951
              info.text = std::string( "//" ) + info.text;
2,456 ✔
1952
          }
1953
          auto lastchar = info.text.find_last_not_of( ' ' );
1,283 ✔
1954
          info.text.erase( info.text.begin() + lastchar + 1, info.text.end() );
1,283 ✔
1955
        }
1956
      }
1957
      else
1958
      {
1959
        info.context = FmtContext::COMMENT;
34 ✔
1960
        if ( compilercfg.FormatterFormatInsideComments )
34 ✔
1961
        {
1962
          info.text.erase( 0, 2 );                                  // remove /*
34 ✔
1963
          info.text.erase( info.text.end() - 2, info.text.end() );  // remove */
34 ✔
1964
          auto firstchar = info.text.find_first_not_of( " \t" );
34 ✔
1965
          // remove remaining whitespace
1966
          info.text.erase( 0, firstchar );
34 ✔
1967
          auto lastchar = info.text.find_last_not_of( " \t" );
34 ✔
1968
          info.text.erase( info.text.begin() + lastchar + 1, info.text.end() );
34 ✔
1969
          if ( info.text.empty() )
34 ✔
1970
            info.text = std::string( "/*" ) + info.text + "*/";
×
1971
          else
1972
          {
1973
            std::string text = "/*";
34 ✔
1974
            // if its in the style of "/** blubb" or "/*\n"  dont add whitespace
1975
            if ( info.text.front() != '\n' && info.text.front() != '\r' &&
65 ✔
1976
                 info.text.front() != '*' )
31 ✔
1977
              text += ' ';
10 ✔
1978
            text += info.text;
34 ✔
1979
            // if its in the style of "blubb **/" or "\n*/"  dont add whitespace
1980
            if ( info.text.back() != '\n' && info.text.back() != '\r' && info.text.back() != '*' )
34 ✔
1981
              text += ' ';
10 ✔
1982

1983
            // detect aligned "*/"
1984
            // /*
1985
            //  *
1986
            //  */
1987
            if ( info.text.back() == '\n' || info.text.back() == '\r' )
34 ✔
1988
            {
1989
              auto lastnewline = text.find_last_of( "\n\r", text.size() - 2 );
3 ✔
1990
              if ( lastnewline != std::string::npos && lastnewline + 2 < text.size() )
3 ✔
1991
              {
1992
                if ( text[lastnewline + 1] == ' ' && text[lastnewline + 2] == '*' )
1 ✔
1993
                  text += ' ';
×
1994
              }
1995
            }
1996
            text += "*/";
34 ✔
1997
            info.text = text;
34 ✔
1998
          }
34 ✔
1999
        }
2000
        // split lines to use correct linenendings
2001
        std::string rawtext = std::move( info.text );
34 ✔
2002
        info.text.clear();
34 ✔
2003
        for ( size_t ri = 0; ri < rawtext.size(); ++ri )
3,452 ✔
2004
        {
2005
          if ( rawtext[ri] == '\r' && ri + 1 < rawtext.size() && rawtext[ri + 1] == '\n' )
3,418 ✔
2006
          {
2007
            ++ri;
×
2008
            auto lastchar = info.text.find_last_not_of( ' ' );
×
2009
            info.text.erase( info.text.begin() + lastchar + 1, info.text.end() );
×
2010
            info.text += compilercfg.FormatterWindowsLineEndings ? "\r\n" : "\n";
×
2011
          }
2012
          else if ( rawtext[ri] == '\r' || rawtext[ri] == '\n' )
3,418 ✔
2013
          {
2014
            auto lastchar = info.text.find_last_not_of( ' ' );
136 ✔
2015
            info.text.erase( info.text.begin() + lastchar + 1, info.text.end() );
136 ✔
2016
            info.text += compilercfg.FormatterWindowsLineEndings ? "\r\n" : "\n";
136 ✔
2017
          }
2018
          else
2019
            info.text += rawtext[ri];
3,282 ✔
2020
        }
2021
      }
34 ✔
2022
      info.pos = startpos.start;
1,317 ✔
2023
      info.pos_end = endpos.end;
1,317 ✔
2024
      comments.emplace_back( std::move( info ) );
1,317 ✔
2025
    }
1,317 ✔
2026
  }
2027
  return comments;
710 ✔
2028
}
710 ✔
2029
}  // namespace Pol::Bscript::Compiler
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc