Bug 1497446 - Porting binsource generator to binjs_meta 0.4.3. r=efaust
☠☠ backed out by c55cc4953755 ☠ ☠
authorDavid Teller <dteller@mozilla.com>
Wed, 10 Oct 2018 16:27:26 +0200
changeset 496825 8f5207ccd12f9a81f367ef3b312462d3665bcc76
parent 496824 7a60706c7063d3de4c0a395bda5ffbc5a467c262
child 496826 006cd7f96ea3669361b1b61e759b374f27095466
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersefaust
bugs1497446
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1497446 - Porting binsource generator to binjs_meta 0.4.3. r=efaust Since binjs_meta 0.4.* introduces PropertyKey and IdentifierName, we now handle these variants of strings.
js/src/frontend/BinSource-auto.cpp
js/src/frontend/BinSource.webidl_
js/src/frontend/BinToken.h
js/src/frontend/binsource/Cargo.toml
js/src/frontend/binsource/src/main.rs
--- a/js/src/frontend/BinSource-auto.cpp
+++ b/js/src/frontend/BinSource-auto.cpp
@@ -2082,17 +2082,17 @@ BinASTParser<Tok>::parseInterfaceAsserte
     }
     auto result = Ok();
     return result;
 }
 
 
 /*
  interface AssertedBoundName : Node {
-    IdentifierName name;
+    [IdentifierName] string name;
     bool isCaptured;
  }
 */
 template<typename Tok> JS::Result<Ok>
 BinASTParser<Tok>::parseAssertedBoundName(
         AssertedScopeKind scopeKind)
 {
     BinKind kind;
@@ -2119,17 +2119,17 @@ BinASTParser<Tok>::parseInterfaceAsserte
     BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Name, BinField::IsCaptured };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
     RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readAtom());
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
 
     BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool());
     ParseContext::Scope* scope;
     DeclarationKind declKind;
     MOZ_TRY(getBoundScope(scopeKind, scope, declKind));
     MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured));
     auto result = Ok();
     return result;
@@ -2187,17 +2187,17 @@ BinASTParser<Tok>::parseInterfaceAsserte
     }
     auto result = Ok();
     return result;
 }
 
 
 /*
  interface AssertedDeclaredName : Node {
-    IdentifierName name;
+    [IdentifierName] string name;
     AssertedDeclaredKind kind;
     bool isCaptured;
  }
 */
 template<typename Tok> JS::Result<Ok>
 BinASTParser<Tok>::parseAssertedDeclaredName(
         AssertedScopeKind scopeKind)
 {
@@ -2225,17 +2225,17 @@ BinASTParser<Tok>::parseInterfaceAsserte
     BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::Name, BinField::Kind, BinField::IsCaptured };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
     RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readAtom());
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
 
     BINJS_MOZ_TRY_DECL(kind_, parseAssertedDeclaredKind());
 
     BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool());
     ParseContext::Scope* scope;
     DeclarationKind declKind;
     MOZ_TRY(getDeclaredScope(scopeKind, kind_, scope, declKind));
     MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured));
@@ -2252,17 +2252,17 @@ BinASTParser<Tok>::parseInterfaceAsserte
     BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Name, BinField::IsCaptured };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
     RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readAtom());
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
 
     BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool());
     ParseContext::Scope* scope;
     DeclarationKind declKind;
     MOZ_TRY(getBoundScope(scopeKind, scope, declKind));
     MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured));
     auto result = Ok();
     return result;
@@ -2339,17 +2339,17 @@ BinASTParser<Tok>::parseInterfaceAsserte
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::Index, BinField::Name, BinField::IsCaptured };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
     BINJS_MOZ_TRY_DECL(index, tokenizer_->readUnsignedLong());
 
     RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readAtom());
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
     // FIXME: The following checks should be performed inside
     // checkPositionalParameterIndices to match the spec's order
     // (bug 1490976).
     if (index >= positionalParams.get().length()) {
         return raiseError("AssertedPositionalParameterName.length out of range");
     }
     if (positionalParams.get()[index]) {
         return raiseError("AssertedPositionalParameterName has duplicate entry for the same index");
@@ -2373,17 +2373,17 @@ BinASTParser<Tok>::parseInterfaceAsserte
     BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
     const BinField expected_fields[2] = { BinField::Name, BinField::IsCaptured };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
     RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readAtom());
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
 
     BINJS_MOZ_TRY_DECL(isCaptured, tokenizer_->readBool());
     ParseContext::Scope* scope;
     DeclarationKind declKind;
     MOZ_TRY(getBoundScope(scopeKind, scope, declKind));
     MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured));
     auto result = Ok();
     return result;
@@ -2514,17 +2514,17 @@ BinASTParser<Tok>::parseInterfaceAssignm
 
     BINJS_TRY_DECL(result, factory_.newAssignment(ParseNodeKind::Assign, binding, expression));
     return result;
 }
 
 
 /*
  interface AssignmentTargetIdentifier : Node {
-    Identifier name;
+    [IdentifierName] string name;
  }
 */
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseAssignmentTargetIdentifier()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
@@ -2547,17 +2547,17 @@ BinASTParser<Tok>::parseInterfaceAssignm
     BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Name };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
     RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readAtom());
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
 
     if (!IsIdentifier(name)) {
         return raiseError("Invalid identifier");
     }
     BINJS_TRY(usedNames_.noteUse(cx_, name, parseContext_->scriptId(), parseContext_->innermostScope()->id()));
     BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));
     return result;
 }
@@ -2697,17 +2697,17 @@ BinASTParser<Tok>::parseInterfaceBinaryE
         result = list;
     }
     return result;
 }
 
 
 /*
  interface BindingIdentifier : Node {
-    Identifier name;
+    [IdentifierName] string name;
  }
 */
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseBindingIdentifier()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
@@ -2730,17 +2730,17 @@ BinASTParser<Tok>::parseInterfaceBinding
     BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Name };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
     RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readAtom());
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
 
     if (!IsIdentifier(name)) {
         return raiseError("Invalid identifier");
     }
     BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));
     return result;
 }
 
@@ -3536,18 +3536,18 @@ template<typename Tok> JS::Result<ParseN
 BinASTParser<Tok>::parseInterfaceExportFrom(const size_t start, const BinKind kind, const BinFields& fields)
 {
     return raiseError("FIXME: Not implemented yet (ExportFrom)");
 }
 
 
 /*
  interface ExportFromSpecifier : Node {
-    IdentifierName name;
-    IdentifierName? exportedName;
+    [IdentifierName] string name;
+    [IdentifierName] string? exportedName;
  }
 */
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseExportFromSpecifier()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
@@ -3568,17 +3568,17 @@ BinASTParser<Tok>::parseInterfaceExportF
 {
     return raiseError("FIXME: Not implemented yet (ExportFromSpecifier)");
 }
 
 
 /*
  interface ExportLocalSpecifier : Node {
     IdentifierExpression name;
-    IdentifierName? exportedName;
+    [PropertyKey] string? exportedName;
  }
 */
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseExportLocalSpecifier()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
@@ -3975,17 +3975,17 @@ BinASTParser<Tok>::parseInterfaceGetterC
     *bodyOut = body;
     auto result = Ok();
     return result;
 }
 
 
 /*
  interface IdentifierExpression : Node {
-    Identifier name;
+    [IdentifierName] string name;
  }
 */
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseIdentifierExpression()
 {
     BinKind kind;
     BinFields fields(cx_);
     AutoTaggedTuple guard(*tokenizer_);
@@ -4008,17 +4008,17 @@ BinASTParser<Tok>::parseInterfaceIdentif
     BINJS_TRY(CheckRecursionLimit(cx_));
 
 #if defined(DEBUG)
     const BinField expected_fields[1] = { BinField::Name };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
     RootedAtom name(cx_);
-    MOZ_TRY_VAR(name, tokenizer_->readAtom());
+    MOZ_TRY_VAR(name, tokenizer_->readIdentifierName());
 
     if (!IsIdentifier(name)) {
         return raiseError("Invalid identifier");
     }
     BINJS_TRY(usedNames_.noteUse(cx_, name, parseContext_->scriptId(), parseContext_->innermostScope()->id()));
     BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_));
     return result;
 }
@@ -4054,17 +4054,17 @@ template<typename Tok> JS::Result<ParseN
 BinASTParser<Tok>::parseInterfaceImportNamespace(const size_t start, const BinKind kind, const BinFields& fields)
 {
     return raiseError("FIXME: Not implemented yet (ImportNamespace)");
 }
 
 
 /*
  interface ImportSpecifier : Node {
-    IdentifierName? name;
+    [PropertyKey] string? name;
     BindingIdentifier binding;
  }
 */
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseImportSpecifier()
 {
     BinKind kind;
     BinFields fields(cx_);
@@ -4595,17 +4595,17 @@ BinASTParser<Tok>::parseInterfaceStaticM
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
     size_t nameStart;
 
     BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
     RootedAtom property(cx_);
     {
         nameStart = tokenizer_->offset();
-        MOZ_TRY_VAR(property, tokenizer_->readAtom());
+        MOZ_TRY_VAR(property, tokenizer_->readPropertyKey());
 
     }
 
     BINJS_TRY_DECL(name, factory_.newPropertyName(property->asPropertyName(), tokenizer_->pos(nameStart)));
     BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, name));
     return result;
 }
 
@@ -4620,17 +4620,17 @@ BinASTParser<Tok>::parseInterfaceStaticM
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
     size_t nameStart;
 
     BINJS_MOZ_TRY_DECL(object, parseExpressionOrSuper());
     RootedAtom property(cx_);
     {
         nameStart = tokenizer_->offset();
-        MOZ_TRY_VAR(property, tokenizer_->readAtom());
+        MOZ_TRY_VAR(property, tokenizer_->readPropertyKey());
 
     }
 
     BINJS_TRY_DECL(name, factory_.newPropertyName(property->asPropertyName(), tokenizer_->pos(nameStart)));
     BINJS_TRY_DECL(result, factory_.newPropertyAccess(object, name));
     return result;
 }
 
--- a/js/src/frontend/BinSource.webidl_
+++ b/js/src/frontend/BinSource.webidl_
@@ -1,14 +1,15 @@
 // Type aliases and enums.
 
 typedef FrozenArray<(SpreadElement or Expression)> Arguments;
 typedef DOMString string;
 typedef string Identifier;
 typedef string IdentifierName;
+typedef string PropertyKey;
 typedef string Label;
 
 enum VariableDeclarationKind {
   "var",
   "let",
   "const"
 };
 
--- a/js/src/frontend/BinToken.h
+++ b/js/src/frontend/BinToken.h
@@ -213,21 +213,23 @@ namespace frontend {
     F(OptionalAssignmentTarget, "OptionalAssignmentTarget") \
     F(OptionalBinding, "OptionalBinding") \
     F(OptionalBindingIdentifier, "OptionalBindingIdentifier") \
     F(OptionalBindingOrBindingWithInitializer, "OptionalBindingOrBindingWithInitializer") \
     F(OptionalCatchClause, "OptionalCatchClause") \
     F(OptionalExpression, "OptionalExpression") \
     F(OptionalIdentifierName, "OptionalIdentifierName") \
     F(OptionalLabel, "OptionalLabel") \
+    F(OptionalPropertyKey, "OptionalPropertyKey") \
     F(OptionalSpreadElementOrExpression, "OptionalSpreadElementOrExpression") \
     F(OptionalStatement, "OptionalStatement") \
     F(OptionalVariableDeclarationOrExpression, "OptionalVariableDeclarationOrExpression") \
     F(Parameter, "Parameter") \
     F(Program, "Program") \
+    F(PropertyKey, "PropertyKey") \
     F(PropertyName, "PropertyName") \
     F(ReturnStatement, "ReturnStatement") \
     F(Script, "Script") \
     F(Setter, "Setter") \
     F(SetterContents, "SetterContents") \
     F(ShorthandProperty, "ShorthandProperty") \
     F(SimpleAssignmentTarget, "SimpleAssignmentTarget") \
     F(SpreadElement, "SpreadElement") \
@@ -262,17 +264,17 @@ namespace frontend {
 
 enum class BinKind {
 #define EMIT_ENUM(name, _) name,
     FOR_EACH_BIN_KIND(EMIT_ENUM)
 #undef EMIT_ENUM
 };
 
 // The number of distinct values of BinKind.
-const size_t BINKIND_LIMIT = 198;
+const size_t BINKIND_LIMIT = 200;
 
 
 
 
 /**
  * The different variants of Binary AST string enums, as per
  * the specifications of Binary AST, as a single macro and
  * `enum class`.
--- a/js/src/frontend/binsource/Cargo.toml
+++ b/js/src/frontend/binsource/Cargo.toml
@@ -1,13 +1,13 @@
 [package]
-name = "binsource"
-version = "0.1.0"
+name = "binast"
+version = "0.1.1"
 authors = ["David Teller <D.O.Teller@gmail.com>"]
 
 [dependencies]
-binjs_meta = "^0.3.10"
+binjs_meta = "^0.4.3"
 clap = "^2"
 env_logger = "^0.5.6"
 itertools = "^0.7.6"
 log = "0.4"
 yaml-rust = "^0.4"
-webidl = "^0.6.0"
+webidl = "^0.8"
--- a/js/src/frontend/binsource/src/main.rs
+++ b/js/src/frontend/binsource/src/main.rs
@@ -544,17 +544,17 @@ struct CPPExporter {
 impl CPPExporter {
     fn new(syntax: Spec, rules: GlobalRules) -> Self {
         let mut list_parsers_to_generate = vec![];
         let mut option_parsers_to_generate = vec![];
         for (parser_node_name, typedef) in syntax.typedefs_by_name() {
             if typedef.is_optional() {
                 let content_name = TypeName::type_spec(typedef.spec());
                 let content_node_name = syntax.get_node_name(&content_name)
-                    .unwrap_or_else(|| panic!("While generating an option parser, could not find node name {}", content_name))
+                    .unwrap_or_else(|| panic!("While generating an option parser, could not find node name \"{}\"", content_name))
                     .clone();
                 debug!(target: "generate_spidermonkey", "CPPExporter::new adding optional typedef {:?} => {:?} => {:?}",
                     parser_node_name,
                     content_name,
                     content_node_name);
                 option_parsers_to_generate.push(OptionParserData {
                     name: parser_node_name.clone(),
                     elements: content_node_name
@@ -708,16 +708,20 @@ impl CPPExporter {
                         _ => {}
                     }
                 },
                 _ => {}
             }
             refgraph.insert(string_from_nodename(&parser.name), edges);
         }
 
+        // 6. Primitive values.
+        refgraph.insert(Rc::new("IdentifierName".to_string()), HashSet::new());
+        refgraph.insert(Rc::new("PropertyKey".to_string()), HashSet::new());
+
         self.refgraph = refgraph;
     }
 
     /// Trace the reference graph from the node with `name and mark all nodes
     /// as used. `name` is the name of the method, without leading "parse".
     fn trace(&mut self, name: Rc<String>) {
         self.refgraph.trace(name)
     }
@@ -1471,16 +1475,75 @@ impl CPPExporter {
 }}
 
 ",
                                 first_line = first_line,
                                 build = build_result,
                             ));
                         }
                     }
+                    &TypeSpec::IdentifierName => {
+                        let build_result = rules_for_this_node.init.reindent("    ");
+                        let first_line = self.get_method_definition_start(&parser.name, "", "",
+                                                                          &extra_params);
+                        if build_result.len() == 0 {
+                            buffer.push_str(&format!("{first_line}
+{{
+    return raiseError(\"FIXME: Not implemented yet ({kind})\");
+}}
+
+",
+                                first_line = first_line,
+                                kind = parser.name.to_str()));
+                        } else {
+                            buffer.push_str(&format!("{first_line}
+{{
+    BINJS_MOZ_TRY_DECL(result, tokenizer_->readMaybeIdentifierName());
+
+{build}
+
+    return result;
+}}
+
+",
+                                first_line = first_line,
+                                build = build_result,
+                            ));
+                        }
+                    }
+                    &TypeSpec::PropertyKey => {
+                        debug!(target: "generate_spidermonkey", "Generating method for PropertyKey: {:?}", parser.name);
+                        let build_result = rules_for_this_node.init.reindent("    ");
+                        let first_line = self.get_method_definition_start(&parser.name, "", "",
+                                                                          &extra_params);
+                        if build_result.len() == 0 {
+                            buffer.push_str(&format!("{first_line}
+{{
+    return raiseError(\"FIXME: Not implemented yet ({kind})\");
+}}
+
+",
+                                first_line = first_line,
+                                kind = parser.name.to_str()));
+                        } else {
+                            buffer.push_str(&format!("{first_line}
+{{
+    BINJS_MOZ_TRY_DECL(result, tokenizer_->readMaybePropertyKey());
+
+{build}
+
+    return result;
+}}
+
+",
+                                first_line = first_line,
+                                build = build_result,
+                            ));
+                        }
+                    }
                     _else => unimplemented!("{:?}", _else)
                 }
             }
             NamedType::StringEnum(_) => {
                 unimplemented!()
             }
         }
     }
@@ -1599,16 +1662,36 @@ impl CPPExporter {
                     warn!("Internal error: We shouldn't have any `void` types at this stage.");
                     (Some(format!("// Skipping void field {}", field.name().to_str())),
                         None)
                 }
                 Some(IsNullable { is_nullable: false, content: Primitive::String }) => {
                     (Some(format!("RootedAtom {var_name}(cx_);", var_name = var_name)),
                         Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readAtom());", var_name = var_name)))
                 }
+                Some(IsNullable { is_nullable: false, content: Primitive::IdentifierName }) => {
+                    (Some(format!("RootedAtom {var_name}(cx_);", var_name = var_name)),
+                        Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readIdentifierName());", var_name = var_name)))
+                }
+                Some(IsNullable { is_nullable: false, content: Primitive::PropertyKey }) => {
+                    (Some(format!("RootedAtom {var_name}(cx_);", var_name = var_name)),
+                        Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readPropertyKey());", var_name = var_name)))
+                }
+                Some(IsNullable { is_nullable: true, content: Primitive::String }) => {
+                    (Some(format!("RootedAtom {var_name}(cx_);", var_name = var_name)),
+                        Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readMaybeAtom());", var_name = var_name)))
+                }
+                Some(IsNullable { is_nullable: true, content: Primitive::IdentifierName }) => {
+                    (Some(format!("RootedAtom {var_name}(cx_);", var_name = var_name)),
+                        Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readMaybeIdentifierName());", var_name = var_name)))
+                }
+                Some(IsNullable { is_nullable: true, content: Primitive::PropertyKey }) => {
+                    (Some(format!("RootedAtom {var_name}(cx_);", var_name = var_name)),
+                        Some(format!("MOZ_TRY_VAR({var_name}, tokenizer_->readMaybePropertyKey());", var_name = var_name)))
+                }
                 _else => {
                     let typename = TypeName::type_(field.type_());
                     let name = self.syntax.get_node_name(typename.to_str())
                         .expect("NodeName for the field type should exist.");
                     let field_extra_args = rules_for_this_field.extra_args;
 
                     let (decl_var, call_kind) = if needs_block {
                         (Some(format!("{typename} {var_name};",
@@ -1621,17 +1704,16 @@ impl CPPExporter {
                     };
 
                     (decl_var,
                      Some(self.get_method_call(var_name.to_str(),
                                                &name, "", "", &field_extra_args,
                                                call_kind)))
                 }
             };
-
             let rendered = {
                 if rules_for_this_field.replace.is_some() {
                     for &(condition, rule_name) in &[
                         (rules_for_this_field.before_field.is_some(), "before:"),
                         (rules_for_this_field.after_field.is_some(), "after:"),
                         (rules_for_this_field.declare.is_some(), "declare:"),
                     ] {
                         if condition {