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

polserver / polserver / 21108840797

18 Jan 2026 08:35AM UTC coverage: 60.508% (+0.02%) from 60.492%
21108840797

push

github

web-flow
ClangTidy readability-else-after-return (#857)

* trigger tidy

* Automated clang-tidy change: readability-else-after-return

* compile test

* rerun

* Automated clang-tidy change: readability-else-after-return

* trigger..

* Automated clang-tidy change: readability-else-after-return

* manually removed a few

* Automated clang-tidy change: readability-else-after-return

* removed duplicate code

* fix remaining warnings

* fixed scope

---------

Co-authored-by: Clang Tidy <clang-tidy@users.noreply.github.com>

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

46 existing lines in 25 files now uncovered.

44448 of 73458 relevant lines covered (60.51%)

525066.38 hits per line

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

89.54
/pol-core/bscript/compiler/astbuilder/SimpleStatementBuilder.cpp
1
#include "SimpleStatementBuilder.h"
2

3
#include "bscript/compiler/Report.h"
4
#include "bscript/compiler/ast/BinaryOperator.h"
5
#include "bscript/compiler/ast/BindingStatement.h"
6
#include "bscript/compiler/ast/ConstDeclaration.h"
7
#include "bscript/compiler/ast/DebugStatementMarker.h"
8
#include "bscript/compiler/ast/ElementIndexes.h"
9
#include "bscript/compiler/ast/EnumDeclaration.h"
10
#include "bscript/compiler/ast/Expression.h"
11
#include "bscript/compiler/ast/Identifier.h"
12
#include "bscript/compiler/ast/IndexBinding.h"
13
#include "bscript/compiler/ast/IntegerValue.h"
14
#include "bscript/compiler/ast/JumpStatement.h"
15
#include "bscript/compiler/ast/ReturnStatement.h"
16
#include "bscript/compiler/ast/SequenceBinding.h"
17
#include "bscript/compiler/ast/StringValue.h"
18
#include "bscript/compiler/ast/VarStatement.h"
19
#include "bscript/compiler/ast/VariableBinding.h"
20
#include "bscript/compiler/astbuilder/BuilderWorkspace.h"
21
#include "bscript/compiler/model/CompilerWorkspace.h"
22
#include "bscript/compiler/model/ScopableName.h"
23

24
using EscriptGrammar::EscriptParser;
25

26
namespace Pol::Bscript::Compiler
27
{
28
SimpleStatementBuilder::SimpleStatementBuilder( const SourceFileIdentifier& source_file_identifier,
13,353✔
29
                                                BuilderWorkspace& workspace )
13,353✔
30
    : ExpressionBuilder( source_file_identifier, workspace )
13,353✔
31
{
32
}
13,353✔
33

34
void SimpleStatementBuilder::add_intrusive_debug_marker(
×
35
    antlr4::ParserRuleContext* ctx, std::vector<std::unique_ptr<Statement>>& statements )
36
{
37
  statements.push_back( std::make_unique<DebugStatementMarker>(
×
38
      location_for( *ctx ), ctx->getText(),
×
39
      static_cast<unsigned>( ctx->start->getStartIndex() ) ) );
×
40
}
×
41

42
void SimpleStatementBuilder::add_var_statements(
5,724✔
43
    EscriptParser::VarStatementContext* ctx, const std::string& class_name,
44
    std::vector<std::unique_ptr<Statement>>& statements )
45
{
46
  if ( auto variable_declaration_list = ctx->variableDeclarationList() )
5,724✔
47
  {
48
    for ( auto decl : variable_declaration_list->variableDeclaration() )
11,780✔
49
    {
50
      if ( auto identifier = decl->IDENTIFIER() )
6,058✔
51
      {
52
        auto loc = location_for( *decl );
5,897✔
53
        std::string name = text( identifier );
5,897✔
54
        std::unique_ptr<VarStatement> var_ast;
5,897✔
55

56
        if ( auto initializer_context = decl->variableDeclarationInitializer() )
5,897✔
57
        {
58
          if ( initializer_context->ARRAY() )
5,062✔
59
          {
60
            var_ast = std::make_unique<VarStatement>( loc, class_name, std::move( name ), true );
69✔
61
          }
62
          else
63
          {
64
            auto initializer = variable_initializer( initializer_context );
4,993✔
65
            var_ast = std::make_unique<VarStatement>( loc, class_name, std::move( name ),
9,982✔
66
                                                      std::move( initializer ) );
9,982✔
67
          }
4,991✔
68
        }
69
        else
70
        {
71
          var_ast = std::make_unique<VarStatement>( loc, class_name, std::move( name ) );
835✔
72
        }
73
        statements.push_back( std::move( var_ast ) );
5,895✔
74
      }
5,899✔
75
      else if ( auto binding_decl = decl->bindingDeclaration() )
161✔
76
      {
77
        auto bindings = binding( class_name, binding_decl );
161✔
78
        auto initializer = binding_initializer( decl->bindingDeclarationInitializer() );
161✔
79
        auto binding_ast = std::make_unique<BindingStatement>(
80
            location_for( *decl ), std::move( bindings ), std::move( initializer ) );
161✔
81

82
        statements.push_back( std::move( binding_ast ) );
161✔
83
      }
161✔
84
    }
5,724✔
85
  }
86
}
5,722✔
87

88
std::unique_ptr<Expression> SimpleStatementBuilder::binding_initializer(
161✔
89
    EscriptGrammar::EscriptParser::BindingDeclarationInitializerContext* ctx )
90
{
91
  return expression( ctx->expression() );
161✔
92
}
93

94
std::unique_ptr<Node> SimpleStatementBuilder::binding(
203✔
95
    const std::string& class_name, EscriptGrammar::EscriptParser::BindingDeclarationContext* ctx )
96
{
97
  if ( auto sequence_binding_list = ctx->sequenceBindingList() )
203✔
98
  {
99
    std::vector<std::unique_ptr<Node>> bindings;
111✔
100
    for ( auto* sequence_binding : sequence_binding_list->sequenceBinding() )
445✔
101
    {
102
      if ( auto identifier = sequence_binding->IDENTIFIER() )
334✔
103
      {
104
        bool rest = sequence_binding->ELLIPSIS();
319✔
105
        bindings.push_back( std::make_unique<VariableBinding>(
319✔
106
            location_for( *sequence_binding ), class_name, text( identifier ), rest ) );
638✔
107
      }
108
      else if ( auto binding_decl = sequence_binding->bindingDeclaration() )
15✔
109
      {
110
        bindings.push_back( binding( class_name, binding_decl ) );
15✔
111
      }
112
      else
113
      {
114
        report.error( location_for( *sequence_binding ), "Unsupported indexed binding" );
×
115
        break;
×
116
      }
117
    }
111✔
118
    return std::make_unique<SequenceBinding>( location_for( *ctx ), std::move( bindings ) );
111✔
119
  }
111✔
120
  if ( auto index_binding_list = ctx->indexBindingList() )
92✔
121
  {
122
    std::vector<std::unique_ptr<Expression>> indices;
92✔
123
    std::vector<std::unique_ptr<Node>> bindings;
92✔
124
    for ( auto* index_binding : index_binding_list->indexBinding() )
568✔
125
    {
126
      auto index_identifier = index_binding->IDENTIFIER();
476✔
127
      bool rest = index_binding->ELLIPSIS();
476✔
128

129
      if ( auto expr = index_binding->expression() )
476✔
130
      {
131
        indices.push_back( expression( expr ) );
15✔
132
      }
133
      else if ( index_identifier )
461✔
134
      {
135
        // Only add the index string value if it's not a rest binding.
136
        if ( !rest )
461✔
137
        {
138
          indices.push_back( std::make_unique<StringValue>( location_for( *index_identifier ),
432✔
139
                                                            text( index_identifier ) ) );
864✔
140
        }
141
      }
142
      else
143
      {
144
        report.error( location_for( *index_binding ), "Unsupported binding" );
×
145
        break;
×
146
      }
147

148
      if ( auto binding_ctx = index_binding->binding() )
476✔
149
      {
150
        if ( auto binding_identifier = binding_ctx->IDENTIFIER() )
75✔
151
        {
152
          bindings.push_back( std::make_unique<VariableBinding>(
48✔
153
              location_for( *binding_identifier ), class_name, text( binding_identifier ), rest ) );
96✔
154
        }
155
        else if ( auto binding_decl = binding_ctx->bindingDeclaration() )
27✔
156
        {
157
          bindings.push_back( binding( class_name, binding_decl ) );
27✔
158
        }
159
        else
160
        {
161
          report.error( location_for( *index_binding ), "Unsupported binding" );
×
162
          break;
×
163
        }
164
      }
165
      else
166
      {
167
        bindings.push_back( std::make_unique<VariableBinding>(
401✔
168
            location_for( *index_identifier ), class_name, text( index_identifier ), rest ) );
802✔
169
      }
170
    }
92✔
171

172
    auto element_indexes =
173
        std::make_unique<ElementIndexes>( location_for( *ctx ), std::move( indices ) );
92✔
174

175
    return std::make_unique<IndexBinding>( location_for( *ctx ), std::move( element_indexes ),
184✔
176
                                           std::move( bindings ) );
184✔
177
  }
92✔
178

179
  // Should never happen, as the context check is exhaustive.
NEW
180
  report.error( location_for( *ctx ), "Unsupported binding list" );
×
NEW
181
  return {};
×
182
}
183

184
std::unique_ptr<JumpStatement> SimpleStatementBuilder::break_statement(
458✔
185
    EscriptParser::BreakStatementContext* ctx )
186
{
187
  auto source_location = location_for( *ctx );
458✔
188
  std::string label = ctx->IDENTIFIER() ? text( ctx->IDENTIFIER() ) : "";
458✔
189

190
  return std::make_unique<JumpStatement>( source_location, JumpStatement::Break,
×
191
                                          std::move( label ) );
916✔
192
}
458✔
193

194
std::unique_ptr<ConstDeclaration> SimpleStatementBuilder::const_declaration(
177,584✔
195
    EscriptParser::ConstStatementContext* ctx )
196
{
197
  auto variable_declaration = ctx->constantDeclaration();
177,584✔
198
  auto identifier = text( variable_declaration->IDENTIFIER() );
177,584✔
199
  auto expression_context = variable_declaration->variableDeclarationInitializer()->expression();
177,584✔
200
  auto value = expression( expression_context );
177,584✔
201

202
  return std::make_unique<ConstDeclaration>(
203
      location_for( *ctx ), ScopableName( ScopeName::Global, identifier ), std::move( value ) );
532,752✔
204
}
177,584✔
205

206
std::unique_ptr<JumpStatement> SimpleStatementBuilder::continue_statement(
192✔
207
    EscriptParser::ContinueStatementContext* ctx )
208
{
209
  auto source_location = location_for( *ctx );
192✔
210
  std::string label = ctx->IDENTIFIER() ? text( ctx->IDENTIFIER() ) : "";
192✔
211

212
  return std::make_unique<JumpStatement>( source_location, JumpStatement::Continue,
×
213
                                          std::move( label ) );
384✔
214
}
192✔
215

216
std::unique_ptr<EnumDeclaration> SimpleStatementBuilder::enum_declaration(
55✔
217
    EscriptParser::EnumStatementContext* ctx )
218
{
219
  std::vector<std::string> names;
55✔
220
  std::vector<std::unique_ptr<Expression>> expressions;
55✔
221
  std::string enum_identifier = text( ctx->IDENTIFIER() );
55✔
222
  auto enum_source_location = location_for( *ctx );
55✔
223
  // std::string prefix = "";
224
  ScopeName scope = ScopeName::Global;
55✔
225
  if ( ctx->CLASS() )
55✔
226
  {
227
    scope = ScopeName( enum_identifier );
21✔
228

229
    if ( auto itr = workspace.compiler_workspace.all_class_locations.find( enum_identifier );
21✔
230
         itr != workspace.compiler_workspace.all_class_locations.end() )
21✔
231
    {
232
      auto& previous = ( *itr ).second;
4✔
233
      report.error( enum_source_location,
4✔
234
                    "Class '{}' defined more than once.\n"
235
                    "  Previous declaration: {}",
236
                    enum_identifier, previous );
237
    }
238
    else
239
    {
240
      workspace.compiler_workspace.all_class_locations.emplace( enum_identifier,
17✔
241
                                                                enum_source_location );
242
    }
243
  }
244
  if ( auto enum_list = ctx->enumList() )
55✔
245
  {
246
    std::string last_identifier;
55✔
247
    for ( auto entry : enum_list->enumListEntry() )
193✔
248
    {
249
      auto source_location = location_for( *entry );
138✔
250
      std::string identifier = text( entry->IDENTIFIER() );
138✔
251
      std::unique_ptr<Expression> value;
138✔
252
      if ( auto expr_ctx = entry->expression() )
138✔
253
      {
254
        value = expression( expr_ctx );
77✔
255
      }
256
      else if ( !last_identifier.empty() )
61✔
257
      {
258
        // The optimizer runs later, so we don't necessarily know the value of
259
        // the previous enum value.  The optimizer will sort it out.
260
        auto lhs = std::make_unique<Identifier>( source_location,
261
                                                 ScopableName( scope, last_identifier ).string() );
44✔
262
        auto one = std::make_unique<IntegerValue>( source_location, 1 );
44✔
263
        value = std::make_unique<BinaryOperator>( source_location, std::move( lhs ), "+", TOK_ADD,
88✔
264
                                                  std::move( one ) );
88✔
265
      }
44✔
266
      else
267
      {
268
        value = std::make_unique<IntegerValue>( source_location, 0 );
17✔
269
      }
270
      bool allow_overwrite = true;
138✔
271
      auto constant = std::make_unique<ConstDeclaration>( location_for( *entry ),
138✔
272
                                                          ScopableName( scope, identifier ),
276✔
273
                                                          std::move( value ), allow_overwrite );
276✔
274
      workspace.compiler_workspace.const_declarations.push_back( std::move( constant ) );
138✔
275

276
      last_identifier = identifier;
138✔
277
    }
193✔
278
  }
55✔
279

280
  return std::make_unique<EnumDeclaration>( enum_source_location, std::move( enum_identifier ),
55✔
281
                                            std::move( names ), std::move( expressions ) );
165✔
282
}
55✔
283

284
std::unique_ptr<Expression> SimpleStatementBuilder::variable_initializer(
4,993✔
285
    EscriptParser::VariableDeclarationInitializerContext* ctx )
286
{
287
  if ( auto expr = ctx->expression() )
4,993✔
288
    return expression( expr );
4,993✔
NEW
289
  return std::unique_ptr<Expression>( new StringValue( location_for( *ctx ), "" ) );
×
290
}
291

292
std::unique_ptr<ReturnStatement> SimpleStatementBuilder::return_statement(
4,805✔
293
    EscriptParser::ReturnStatementContext* ctx )
294
{
295
  auto source_location = location_for( *ctx );
4,805✔
296

297
  std::unique_ptr<Expression> result;
4,805✔
298

299
  // Always emit the expression if it exists, so we can get semantic analysis
300
  // errors.
301
  if ( auto expression_ctx = ctx->expression() )
4,805✔
302
  {
303
    result = expression( expression_ctx );
4,778✔
304
  }
305
  else
306
  {
307
    // Only emit the empty string if we're not in a constructor function.
308
    if ( !in_constructor_function.top() )
27✔
309
      result = std::unique_ptr<Expression>( new StringValue( source_location, "" ) );
24✔
310
  }
311

312
  return std::make_unique<ReturnStatement>( source_location, std::move( result ) );
9,610✔
313
}
4,805✔
314

315
}  // 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